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_PROCESS_FORK
,
87 LTT_EVENT_KTHREAD_CREATE
,
88 LTT_EVENT_PROCESS_EXIT
,
89 LTT_EVENT_PROCESS_FREE
,
91 LTT_EVENT_PROCESS_STATE
,
92 LTT_EVENT_STATEDUMP_END
,
93 LTT_EVENT_FUNCTION_ENTRY
,
94 LTT_EVENT_FUNCTION_EXIT
,
95 LTT_EVENT_THREAD_BRAND
,
96 LTT_EVENT_REQUEST_ISSUE
,
97 LTT_EVENT_REQUEST_COMPLETE
,
98 LTT_EVENT_LIST_INTERRUPT
,
99 LTT_EVENT_SYS_CALL_TABLE
,
100 LTT_EVENT_SOFTIRQ_VEC
,
101 LTT_EVENT_KPROBE_TABLE
,
107 LTT_FIELD_SYSCALL_ID
,
110 LTT_FIELD_SOFT_IRQ_ID
,
113 LTT_FIELD_PREV_STATE
,
114 LTT_FIELD_PARENT_PID
,
118 LTT_FIELD_CHILD_TGID
,
137 LTTV_STATE_MODE_UNKNOWN
,
138 LTTV_STATE_USER_MODE
,
145 LTTV_STATE_SUBMODE_UNKNOWN
,
146 LTTV_STATE_SUBMODE_NONE
;
150 LTTV_STATE_WAIT_FORK
,
159 LTTV_STATE_UNBRANDED
;
162 LTTV_STATE_USER_THREAD
,
163 LTTV_STATE_KERNEL_THREAD
;
181 LTTV_BDEV_BUSY_READING
,
182 LTTV_BDEV_BUSY_WRITING
;
185 LTTV_STATE_TRACEFILES
,
186 LTTV_STATE_PROCESSES
,
188 LTTV_STATE_RUNNING_PROCESS
,
190 LTTV_STATE_SAVED_STATES
,
191 LTTV_STATE_SAVED_STATES_TIME
,
194 LTTV_STATE_NAME_TABLES
,
195 LTTV_STATE_TRACE_STATE_USE_COUNT
,
196 LTTV_STATE_RESOURCE_CPUS
,
197 LTTV_STATE_RESOURCE_CPUS_COUNT
,
198 LTTV_STATE_RESOURCE_IRQS
,
199 LTTV_STATE_RESOURCE_SOFT_IRQS
,
200 LTTV_STATE_RESOURCE_TRAPS
,
201 LTTV_STATE_RESOURCE_BLKDEVS
;
203 static void create_max_time(LttvTraceState
*tcs
);
205 static void get_max_time(LttvTraceState
*tcs
);
207 static void free_max_time(LttvTraceState
*tcs
);
209 static void create_name_tables(LttvTraceState
*tcs
);
211 static void get_name_tables(LttvTraceState
*tcs
);
213 static void free_name_tables(LttvTraceState
*tcs
);
215 static void free_saved_state(LttvTraceState
*tcs
);
217 static void lttv_state_free_process_table(GHashTable
*processes
);
219 static void lttv_trace_states_read_raw(LttvTraceState
*tcs
, FILE *fp
,
220 GPtrArray
*quarktable
);
222 /* Resource function prototypes */
223 static LttvBdevState
*get_hashed_bdevstate(LttvTraceState
*ts
, guint16 devcode
);
224 static LttvBdevState
*bdevstate_new(void);
225 static void bdevstate_free(LttvBdevState
*);
226 static void bdevstate_free_cb(gpointer key
, gpointer value
, gpointer user_data
);
227 static LttvBdevState
*bdevstate_copy(LttvBdevState
*bds
);
230 #if (__SIZEOF_LONG__ == 4)
231 guint
guint64_hash(gconstpointer key
)
233 guint64 ukey
= *(const guint64
*)key
;
235 return (guint
)ukey
^ (guint
)(ukey
>> 32);
238 gboolean
guint64_equal(gconstpointer a
, gconstpointer b
)
240 guint64 ua
= *(const guint64
*)a
;
241 guint64 ub
= *(const guint64
*)b
;
247 void lttv_state_save(LttvTraceState
*self
, LttvAttribute
*container
)
249 LTTV_TRACE_STATE_GET_CLASS(self
)->state_save(self
, container
);
253 void lttv_state_restore(LttvTraceState
*self
, LttvAttribute
*container
)
255 LTTV_TRACE_STATE_GET_CLASS(self
)->state_restore(self
, container
);
259 void lttv_state_state_saved_free(LttvTraceState
*self
,
260 LttvAttribute
*container
)
262 LTTV_TRACE_STATE_GET_CLASS(self
)->state_saved_free(self
, container
);
266 guint
process_hash(gconstpointer key
)
268 guint pid
= ((const LttvProcessState
*)key
)->pid
;
269 return (pid
>>8 ^ pid
>>4 ^ pid
>>2 ^ pid
) ;
273 /* If the hash table hash function is well distributed,
274 * the process_equal should compare different pid */
275 gboolean
process_equal(gconstpointer a
, gconstpointer b
)
277 const LttvProcessState
*process_a
, *process_b
;
280 process_a
= (const LttvProcessState
*)a
;
281 process_b
= (const LttvProcessState
*)b
;
283 if(likely(process_a
->pid
!= process_b
->pid
)) ret
= FALSE
;
284 else if(likely(process_a
->pid
== 0 &&
285 process_a
->cpu
!= process_b
->cpu
)) ret
= FALSE
;
290 static void delete_usertrace(gpointer key
, gpointer value
, gpointer user_data
)
292 g_tree_destroy((GTree
*)value
);
295 static void lttv_state_free_usertraces(GHashTable
*usertraces
)
297 g_hash_table_foreach(usertraces
, delete_usertrace
, NULL
);
298 g_hash_table_destroy(usertraces
);
301 gboolean
rettrue(gpointer key
, gpointer value
, gpointer user_data
)
306 static guint
check_expand(nb
, id
)
311 return max(id
+ 1, nb
* 2);
314 static void expand_name_table(LttvTraceState
*ts
, GQuark
**table
,
315 guint nb
, guint new_nb
)
317 /* Expand an incomplete table */
318 GQuark
*old_table
= *table
;
319 *table
= g_new(GQuark
, new_nb
);
320 memcpy(*table
, old_table
, nb
* sizeof(GQuark
));
323 static void fill_name_table(LttvTraceState
*ts
, GQuark
*table
, guint nb
,
324 guint new_nb
, const char *def_string
)
327 GString
*fe_name
= g_string_new("");
328 for(i
= nb
; i
< new_nb
; i
++) {
329 g_string_printf(fe_name
, "%s %d", def_string
, i
);
330 table
[i
] = g_quark_from_string(fe_name
->str
);
332 g_string_free(fe_name
, TRUE
);
335 static void expand_syscall_table(LttvTraceState
*ts
, int id
)
337 guint new_nb
= check_expand(ts
->nb_syscalls
, id
);
338 if(likely(new_nb
== ts
->nb_syscalls
))
340 expand_name_table(ts
, &ts
->syscall_names
, ts
->nb_syscalls
, new_nb
);
341 fill_name_table(ts
, ts
->syscall_names
, ts
->nb_syscalls
, new_nb
, "syscall");
342 /* Update the table size */
343 ts
->nb_syscalls
= new_nb
;
346 static void expand_kprobe_table(LttvTraceState
*ts
, guint64 ip
, char *symbol
)
348 #if (__SIZEOF_LONG__ == 4)
349 guint64
*ip_ptr
= g_new(guint64
, 1);
350 g_hash_table_insert(ts
->kprobe_hash
, ip_ptr
,
351 (gpointer
)(glong
)g_quark_from_string(symbol
));
353 g_hash_table_insert(ts
->kprobe_hash
, (gpointer
)ip
,
354 (gpointer
)(glong
)g_quark_from_string(symbol
));
358 static void expand_trap_table(LttvTraceState
*ts
, int id
)
360 guint new_nb
= check_expand(ts
->nb_traps
, id
);
362 if(likely(new_nb
== ts
->nb_traps
))
364 expand_name_table(ts
, &ts
->trap_names
, ts
->nb_traps
, new_nb
);
365 fill_name_table(ts
, ts
->trap_names
, ts
->nb_traps
, new_nb
, "trap");
366 /* Update the table size */
367 ts
->nb_traps
= new_nb
;
369 LttvTrapState
*old_table
= ts
->trap_states
;
370 ts
->trap_states
= g_new(LttvTrapState
, new_nb
);
371 memcpy(ts
->trap_states
, old_table
,
372 ts
->nb_traps
* sizeof(LttvTrapState
));
373 for(i
= ts
->nb_traps
; i
< new_nb
; i
++)
374 ts
->trap_states
[i
].running
= 0;
377 static void expand_irq_table(LttvTraceState
*ts
, int id
)
379 guint new_nb
= check_expand(ts
->nb_irqs
, id
);
381 if(likely(new_nb
== ts
->nb_irqs
))
383 expand_name_table(ts
, &ts
->irq_names
, ts
->nb_irqs
, new_nb
);
384 fill_name_table(ts
, ts
->irq_names
, ts
->nb_irqs
, new_nb
, "irq");
386 LttvIRQState
*old_table
= ts
->irq_states
;
387 ts
->irq_states
= g_new(LttvIRQState
, new_nb
);
388 memcpy(ts
->irq_states
, old_table
, ts
->nb_irqs
* sizeof(LttvIRQState
));
389 for(i
= ts
->nb_irqs
; i
< new_nb
; i
++) {
390 ts
->irq_states
[i
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvIRQMode
));
393 /* Update the table size */
394 ts
->nb_irqs
= new_nb
;
397 static void expand_soft_irq_table(LttvTraceState
*ts
, int id
)
399 guint new_nb
= check_expand(ts
->nb_soft_irqs
, id
);
401 if(likely(new_nb
== ts
->nb_soft_irqs
))
403 expand_name_table(ts
, &ts
->soft_irq_names
, ts
->nb_soft_irqs
, new_nb
);
404 fill_name_table(ts
, ts
->soft_irq_names
, ts
->nb_soft_irqs
, new_nb
, "softirq");
406 LttvSoftIRQState
*old_table
= ts
->soft_irq_states
;
407 ts
->soft_irq_states
= g_new(LttvSoftIRQState
, new_nb
);
408 memcpy(ts
->soft_irq_states
, old_table
,
409 ts
->nb_soft_irqs
* sizeof(LttvSoftIRQState
));
410 for(i
= ts
->nb_soft_irqs
; i
< new_nb
; i
++)
411 ts
->soft_irq_states
[i
].running
= 0;
413 /* Update the table size */
414 ts
->nb_soft_irqs
= new_nb
;
418 restore_init_state(LttvTraceState
*self
)
420 guint i
, nb_cpus
, nb_irqs
, nb_soft_irqs
, nb_traps
;
422 //LttvTracefileState *tfcs;
424 LttTime start_time
, end_time
;
426 /* Free the process tables */
427 if(self
->processes
!= NULL
) lttv_state_free_process_table(self
->processes
);
428 if(self
->usertraces
!= NULL
) lttv_state_free_usertraces(self
->usertraces
);
429 self
->processes
= g_hash_table_new(process_hash
, process_equal
);
430 self
->usertraces
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
433 /* Seek time to beginning */
434 // Mathieu : fix : don't seek traceset here : causes inconsistency in seek
435 // closest. It's the tracecontext job to seek the trace to the beginning
436 // anyway : the init state might be used at the middle of the trace as well...
437 //g_tree_destroy(self->parent.ts_context->pqueue);
438 //self->parent.ts_context->pqueue = g_tree_new(compare_tracefile);
440 ltt_trace_time_span_get(self
->parent
.t
, &start_time
, &end_time
);
442 //lttv_process_trace_seek_time(&self->parent, ltt_time_zero);
444 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
445 nb_irqs
= self
->nb_irqs
;
446 nb_soft_irqs
= self
->nb_soft_irqs
;
447 nb_traps
= self
->nb_traps
;
449 /* Put the per cpu running_process to beginning state : process 0. */
450 for(i
=0; i
< nb_cpus
; i
++) {
451 LttvExecutionState
*es
;
452 self
->running_process
[i
] = lttv_state_create_process(self
, NULL
, i
, 0, 0,
453 LTTV_STATE_UNNAMED
, &start_time
);
454 /* We are not sure is it's a kernel thread or normal thread, put the
455 * bottom stack state to unknown */
456 self
->running_process
[i
]->execution_stack
=
457 g_array_set_size(self
->running_process
[i
]->execution_stack
, 1);
458 es
= self
->running_process
[i
]->state
=
459 &g_array_index(self
->running_process
[i
]->execution_stack
,
460 LttvExecutionState
, 0);
461 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
462 es
->s
= LTTV_STATE_UNNAMED
;
464 //self->running_process[i]->state->s = LTTV_STATE_RUN;
465 self
->running_process
[i
]->cpu
= i
;
467 /* reset cpu states */
468 if(self
->cpu_states
[i
].mode_stack
->len
> 0) {
469 g_array_remove_range(self
->cpu_states
[i
].mode_stack
, 0, self
->cpu_states
[i
].mode_stack
->len
);
470 self
->cpu_states
[i
].last_irq
= -1;
471 self
->cpu_states
[i
].last_soft_irq
= -1;
472 self
->cpu_states
[i
].last_trap
= -1;
476 /* reset irq states */
477 for(i
=0; i
<nb_irqs
; i
++) {
478 if(self
->irq_states
[i
].mode_stack
->len
> 0)
479 g_array_remove_range(self
->irq_states
[i
].mode_stack
, 0, self
->irq_states
[i
].mode_stack
->len
);
482 /* reset softirq states */
483 for(i
=0; i
<nb_soft_irqs
; i
++) {
484 self
->soft_irq_states
[i
].pending
= 0;
485 self
->soft_irq_states
[i
].running
= 0;
488 /* reset trap states */
489 for(i
=0; i
<nb_traps
; i
++) {
490 self
->trap_states
[i
].running
= 0;
493 /* reset bdev states */
494 g_hash_table_foreach(self
->bdev_states
, bdevstate_free_cb
, NULL
);
495 //g_hash_table_steal_all(self->bdev_states);
496 g_hash_table_foreach_steal(self
->bdev_states
, rettrue
, NULL
);
499 nb_tracefile
= self
->parent
.tracefiles
->len
;
501 for(i
= 0 ; i
< nb_tracefile
; i
++) {
503 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
504 LttvTracefileContext
*, i
));
505 ltt_trace_time_span_get(self
->parent
.t
, &tfcs
->parent
.timestamp
, NULL
);
506 // tfcs->saved_position = 0;
507 tfcs
->process
= lttv_state_create_process(tfcs
, NULL
,0);
508 tfcs
->process
->state
->s
= LTTV_STATE_RUN
;
509 tfcs
->process
->last_cpu
= tfcs
->cpu_name
;
510 tfcs
->process
->last_cpu_index
= ltt_tracefile_num(((LttvTracefileContext
*)tfcs
)->tf
);
515 //static LttTime time_zero = {0,0};
517 static gint
compare_usertraces(gconstpointer a
, gconstpointer b
,
520 const LttTime
*t1
= (const LttTime
*)a
;
521 const LttTime
*t2
= (const LttTime
*)b
;
523 return ltt_time_compare(*t1
, *t2
);
526 static void free_usertrace_key(gpointer data
)
531 #define MAX_STRING_LEN 4096
534 state_load_saved_states(LttvTraceState
*tcs
)
537 GPtrArray
*quarktable
;
538 const char *trace_path
;
542 tcs
->has_precomputed_states
= FALSE
;
546 gchar buf
[MAX_STRING_LEN
];
549 trace_path
= g_quark_to_string(ltt_trace_name(tcs
->parent
.t
));
550 strncpy(path
, trace_path
, PATH_MAX
-1);
551 count
= strnlen(trace_path
, PATH_MAX
-1);
552 // quarktable : open, test
553 strncat(path
, "/precomputed/quarktable", PATH_MAX
-count
-1);
554 fp
= fopen(path
, "r");
556 quarktable
= g_ptr_array_sized_new(4096);
558 /* Index 0 is null */
560 if(hdr
== EOF
) return;
561 g_assert(hdr
== HDR_QUARKS
);
565 if(hdr
== EOF
) break;
566 g_assert(hdr
== HDR_QUARK
);
567 g_ptr_array_set_size(quarktable
, q
+1);
570 fread(&buf
[i
], sizeof(gchar
), 1, fp
);
571 if(buf
[i
] == '\0' || feof(fp
)) break;
574 len
= strnlen(buf
, MAX_STRING_LEN
-1);
575 g_ptr_array_index (quarktable
, q
) = g_new(gchar
, len
+1);
576 strncpy(g_ptr_array_index (quarktable
, q
), buf
, len
+1);
582 // saved_states : open, test
583 strncpy(path
, trace_path
, PATH_MAX
-1);
584 count
= strnlen(trace_path
, PATH_MAX
-1);
585 strncat(path
, "/precomputed/states", PATH_MAX
-count
-1);
586 fp
= fopen(path
, "r");
590 if(hdr
!= HDR_TRACE
) goto end
;
592 lttv_trace_states_read_raw(tcs
, fp
, quarktable
);
594 tcs
->has_precomputed_states
= TRUE
;
599 /* Free the quarktable */
600 for(i
=0; i
<quarktable
->len
; i
++) {
601 string
= g_ptr_array_index (quarktable
, i
);
604 g_ptr_array_free(quarktable
, TRUE
);
609 init(LttvTracesetState
*self
, LttvTraceset
*ts
)
611 guint i
, j
, nb_trace
, nb_tracefile
, nb_cpu
;
614 LttvTraceContext
*tc
;
618 LttvTracefileState
*tfcs
;
620 LttvAttributeValue v
;
622 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
623 init((LttvTracesetContext
*)self
, ts
);
625 nb_trace
= lttv_traceset_number(ts
);
626 for(i
= 0 ; i
< nb_trace
; i
++) {
627 tc
= self
->parent
.traces
[i
];
628 tcs
= LTTV_TRACE_STATE(tc
);
629 tcs
->save_interval
= LTTV_STATE_SAVE_INTERVAL
;
630 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_TRACE_STATE_USE_COUNT
,
634 if(*(v
.v_uint
) == 1) {
635 create_name_tables(tcs
);
636 create_max_time(tcs
);
638 get_name_tables(tcs
);
641 nb_tracefile
= tc
->tracefiles
->len
;
642 nb_cpu
= ltt_trace_get_num_cpu(tc
->t
);
643 nb_irq
= tcs
->nb_irqs
;
644 tcs
->processes
= NULL
;
645 tcs
->usertraces
= NULL
;
646 tcs
->running_process
= g_new(LttvProcessState
*, nb_cpu
);
648 /* init cpu resource stuff */
649 tcs
->cpu_states
= g_new(LttvCPUState
, nb_cpu
);
650 for(j
= 0; j
<nb_cpu
; j
++) {
651 tcs
->cpu_states
[j
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvCPUMode
));
652 tcs
->cpu_states
[j
].last_irq
= -1;
653 tcs
->cpu_states
[j
].last_soft_irq
= -1;
654 tcs
->cpu_states
[j
].last_trap
= -1;
655 g_assert(tcs
->cpu_states
[j
].mode_stack
!= NULL
);
658 /* init irq resource stuff */
659 tcs
->irq_states
= g_new(LttvIRQState
, nb_irq
);
660 for(j
= 0; j
<nb_irq
; j
++) {
661 tcs
->irq_states
[j
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvIRQMode
));
662 g_assert(tcs
->irq_states
[j
].mode_stack
!= NULL
);
665 /* init soft irq stuff */
666 /* the kernel has a statically fixed max of 32 softirqs */
667 tcs
->soft_irq_states
= g_new(LttvSoftIRQState
, tcs
->nb_soft_irqs
);
669 /* init trap stuff */
670 tcs
->trap_states
= g_new(LttvTrapState
, tcs
->nb_traps
);
672 /* init bdev resource stuff */
673 tcs
->bdev_states
= g_hash_table_new(g_int_hash
, g_int_equal
);
675 restore_init_state(tcs
);
676 for(j
= 0 ; j
< nb_tracefile
; j
++) {
678 LTTV_TRACEFILE_STATE(g_array_index(tc
->tracefiles
,
679 LttvTracefileContext
*, j
));
680 tfcs
->tracefile_name
= ltt_tracefile_name(tfcs
->parent
.tf
);
681 tfcs
->cpu
= ltt_tracefile_cpu(tfcs
->parent
.tf
);
682 tfcs
->cpu_state
= &(tcs
->cpu_states
[tfcs
->cpu
]);
683 if(ltt_tracefile_tid(tfcs
->parent
.tf
) != 0) {
684 /* It's a Usertrace */
685 guint tid
= ltt_tracefile_tid(tfcs
->parent
.tf
);
686 GTree
*usertrace_tree
= (GTree
*)g_hash_table_lookup(tcs
->usertraces
,
687 GUINT_TO_POINTER(tid
));
688 if(!usertrace_tree
) {
689 usertrace_tree
= g_tree_new_full(compare_usertraces
,
690 NULL
, free_usertrace_key
, NULL
);
691 g_hash_table_insert(tcs
->usertraces
,
692 GUINT_TO_POINTER(tid
), usertrace_tree
);
694 LttTime
*timestamp
= g_new(LttTime
, 1);
695 *timestamp
= ltt_interpolate_time_from_tsc(tfcs
->parent
.tf
,
696 ltt_tracefile_creation(tfcs
->parent
.tf
));
697 g_tree_insert(usertrace_tree
, timestamp
, tfcs
);
701 /* See if the trace has saved states */
702 state_load_saved_states(tcs
);
707 fini(LttvTracesetState
*self
)
713 //LttvTracefileState *tfcs;
715 LttvAttributeValue v
;
717 nb_trace
= lttv_traceset_number(LTTV_TRACESET_CONTEXT(self
)->ts
);
718 for(i
= 0 ; i
< nb_trace
; i
++) {
719 tcs
= (LttvTraceState
*)(LTTV_TRACESET_CONTEXT(self
)->traces
[i
]);
720 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_TRACE_STATE_USE_COUNT
,
723 g_assert(*(v
.v_uint
) != 0);
726 if(*(v
.v_uint
) == 0) {
727 free_name_tables(tcs
);
729 free_saved_state(tcs
);
731 g_free(tcs
->running_process
);
732 tcs
->running_process
= NULL
;
733 lttv_state_free_process_table(tcs
->processes
);
734 lttv_state_free_usertraces(tcs
->usertraces
);
735 tcs
->processes
= NULL
;
736 tcs
->usertraces
= NULL
;
738 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
739 fini((LttvTracesetContext
*)self
);
743 static LttvTracesetContext
*
744 new_traceset_context(LttvTracesetContext
*self
)
746 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATE_TYPE
, NULL
));
750 static LttvTraceContext
*
751 new_trace_context(LttvTracesetContext
*self
)
753 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATE_TYPE
, NULL
));
757 static LttvTracefileContext
*
758 new_tracefile_context(LttvTracesetContext
*self
)
760 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATE_TYPE
, NULL
));
764 /* Write the process state of the trace */
766 static void write_process_state(gpointer key
, gpointer value
,
769 LttvProcessState
*process
;
771 LttvExecutionState
*es
;
773 FILE *fp
= (FILE *)user_data
;
778 process
= (LttvProcessState
*)value
;
780 " <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",
781 process
, process
->pid
, process
->tgid
, process
->ppid
,
782 g_quark_to_string(process
->type
),
783 process
->creation_time
.tv_sec
,
784 process
->creation_time
.tv_nsec
,
785 process
->insertion_time
.tv_sec
,
786 process
->insertion_time
.tv_nsec
,
787 g_quark_to_string(process
->name
),
788 g_quark_to_string(process
->brand
),
789 process
->cpu
, process
->free_events
);
791 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
792 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
793 fprintf(fp
, " <ES MODE=\"%s\" SUBMODE=\"%s\" ENTRY_S=%lu ENTRY_NS=%lu",
794 g_quark_to_string(es
->t
), g_quark_to_string(es
->n
),
795 es
->entry
.tv_sec
, es
->entry
.tv_nsec
);
796 fprintf(fp
, " CHANGE_S=%lu CHANGE_NS=%lu STATUS=\"%s\"/>\n",
797 es
->change
.tv_sec
, es
->change
.tv_nsec
, g_quark_to_string(es
->s
));
800 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
801 address
= g_array_index(process
->user_stack
, guint64
, i
);
802 fprintf(fp
, " <USER_STACK ADDRESS=\"%" PRIu64
"\"/>\n",
806 if(process
->usertrace
) {
807 fprintf(fp
, " <USERTRACE NAME=\"%s\" CPU=%u\n/>",
808 g_quark_to_string(process
->usertrace
->tracefile_name
),
809 process
->usertrace
->cpu
);
813 fprintf(fp
, " </PROCESS>\n");
817 void lttv_state_write(LttvTraceState
*self
, LttTime t
, FILE *fp
)
819 guint i
, nb_tracefile
, nb_block
, offset
;
822 LttvTracefileState
*tfcs
;
826 LttEventPosition
*ep
;
830 ep
= ltt_event_position_new();
832 fprintf(fp
,"<PROCESS_STATE TIME_S=%lu TIME_NS=%lu>\n", t
.tv_sec
, t
.tv_nsec
);
834 g_hash_table_foreach(self
->processes
, write_process_state
, fp
);
836 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
837 for(i
=0;i
<nb_cpus
;i
++) {
838 fprintf(fp
," <CPU NUM=%u RUNNING_PROCESS=%u>\n",
839 i
, self
->running_process
[i
]->pid
);
842 nb_tracefile
= self
->parent
.tracefiles
->len
;
844 for(i
= 0 ; i
< nb_tracefile
; i
++) {
846 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
847 LttvTracefileContext
*, i
));
848 fprintf(fp
, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
849 tfcs
->parent
.timestamp
.tv_sec
,
850 tfcs
->parent
.timestamp
.tv_nsec
);
851 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
852 if(e
== NULL
) fprintf(fp
,"/>\n");
854 ltt_event_position(e
, ep
);
855 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
856 fprintf(fp
, " BLOCK=%u OFFSET=%u TSC=%" PRIu64
"/>\n", nb_block
, offset
,
861 fprintf(fp
,"</PROCESS_STATE>\n");
865 static void write_process_state_raw(gpointer key
, gpointer value
,
868 LttvProcessState
*process
;
870 LttvExecutionState
*es
;
872 FILE *fp
= (FILE *)user_data
;
877 process
= (LttvProcessState
*)value
;
878 fputc(HDR_PROCESS
, fp
);
879 //fwrite(&header, sizeof(header), 1, fp);
880 //fprintf(fp, "%s", g_quark_to_string(process->type));
882 fwrite(&process
->type
, sizeof(process
->type
), 1, fp
);
883 //fprintf(fp, "%s", g_quark_to_string(process->name));
885 fwrite(&process
->name
, sizeof(process
->name
), 1, fp
);
886 //fprintf(fp, "%s", g_quark_to_string(process->brand));
888 fwrite(&process
->brand
, sizeof(process
->brand
), 1, fp
);
889 fwrite(&process
->pid
, sizeof(process
->pid
), 1, fp
);
890 fwrite(&process
->free_events
, sizeof(process
->free_events
), 1, fp
);
891 fwrite(&process
->tgid
, sizeof(process
->tgid
), 1, fp
);
892 fwrite(&process
->ppid
, sizeof(process
->ppid
), 1, fp
);
893 fwrite(&process
->cpu
, sizeof(process
->cpu
), 1, fp
);
894 fwrite(&process
->creation_time
, sizeof(process
->creation_time
), 1, fp
);
895 fwrite(&process
->insertion_time
, sizeof(process
->insertion_time
), 1, fp
);
899 " <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",
900 process
, process
->pid
, process
->tgid
, process
->ppid
,
901 g_quark_to_string(process
->type
),
902 process
->creation_time
.tv_sec
,
903 process
->creation_time
.tv_nsec
,
904 process
->insertion_time
.tv_sec
,
905 process
->insertion_time
.tv_nsec
,
906 g_quark_to_string(process
->name
),
907 g_quark_to_string(process
->brand
),
911 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
912 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
915 //fprintf(fp, "%s", g_quark_to_string(es->t));
917 fwrite(&es
->t
, sizeof(es
->t
), 1, fp
);
918 //fprintf(fp, "%s", g_quark_to_string(es->n));
920 fwrite(&es
->n
, sizeof(es
->n
), 1, fp
);
921 //fprintf(fp, "%s", g_quark_to_string(es->s));
923 fwrite(&es
->s
, sizeof(es
->s
), 1, fp
);
924 fwrite(&es
->entry
, sizeof(es
->entry
), 1, fp
);
925 fwrite(&es
->change
, sizeof(es
->change
), 1, fp
);
926 fwrite(&es
->cum_cpu_time
, sizeof(es
->cum_cpu_time
), 1, fp
);
928 fprintf(fp
, " <ES MODE=\"%s\" SUBMODE=\"%s\" ENTRY_S=%lu ENTRY_NS=%lu",
929 g_quark_to_string(es
->t
), g_quark_to_string(es
->n
),
930 es
->entry
.tv_sec
, es
->entry
.tv_nsec
);
931 fprintf(fp
, " CHANGE_S=%lu CHANGE_NS=%lu STATUS=\"%s\"/>\n",
932 es
->change
.tv_sec
, es
->change
.tv_nsec
, g_quark_to_string(es
->s
));
936 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
937 address
= g_array_index(process
->user_stack
, guint64
, i
);
938 fputc(HDR_USER_STACK
, fp
);
939 fwrite(&address
, sizeof(address
), 1, fp
);
941 fprintf(fp
, " <USER_STACK ADDRESS=\"%llu\"/>\n",
946 if(process
->usertrace
) {
947 fputc(HDR_USERTRACE
, fp
);
948 //fprintf(fp, "%s", g_quark_to_string(process->usertrace->tracefile_name));
950 fwrite(&process
->usertrace
->tracefile_name
,
951 sizeof(process
->usertrace
->tracefile_name
), 1, fp
);
952 fwrite(&process
->usertrace
->cpu
, sizeof(process
->usertrace
->cpu
), 1, fp
);
954 fprintf(fp
, " <USERTRACE NAME=\"%s\" CPU=%u\n/>",
955 g_quark_to_string(process
->usertrace
->tracefile_name
),
956 process
->usertrace
->cpu
);
963 void lttv_state_write_raw(LttvTraceState
*self
, LttTime t
, FILE *fp
)
965 guint i
, nb_tracefile
, nb_block
, offset
;
968 LttvTracefileState
*tfcs
;
972 LttEventPosition
*ep
;
976 ep
= ltt_event_position_new();
978 //fprintf(fp,"<PROCESS_STATE TIME_S=%lu TIME_NS=%lu>\n", t.tv_sec, t.tv_nsec);
979 fputc(HDR_PROCESS_STATE
, fp
);
980 fwrite(&t
, sizeof(t
), 1, fp
);
982 g_hash_table_foreach(self
->processes
, write_process_state_raw
, fp
);
984 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
985 for(i
=0;i
<nb_cpus
;i
++) {
987 fwrite(&i
, sizeof(i
), 1, fp
); /* cpu number */
988 fwrite(&self
->running_process
[i
]->pid
,
989 sizeof(self
->running_process
[i
]->pid
), 1, fp
);
990 //fprintf(fp," <CPU NUM=%u RUNNING_PROCESS=%u>\n",
991 // i, self->running_process[i]->pid);
994 nb_tracefile
= self
->parent
.tracefiles
->len
;
996 for(i
= 0 ; i
< nb_tracefile
; i
++) {
998 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
999 LttvTracefileContext
*, i
));
1000 // fprintf(fp, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
1001 // tfcs->parent.timestamp.tv_sec,
1002 // tfcs->parent.timestamp.tv_nsec);
1003 fputc(HDR_TRACEFILE
, fp
);
1004 fwrite(&tfcs
->parent
.timestamp
, sizeof(tfcs
->parent
.timestamp
), 1, fp
);
1005 /* Note : if timestamp if LTT_TIME_INFINITE, there will be no
1006 * position following : end of trace */
1007 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
1009 ltt_event_position(e
, ep
);
1010 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
1011 //fprintf(fp, " BLOCK=%u OFFSET=%u TSC=%llu/>\n", nb_block, offset,
1013 fwrite(&nb_block
, sizeof(nb_block
), 1, fp
);
1014 fwrite(&offset
, sizeof(offset
), 1, fp
);
1015 fwrite(&tsc
, sizeof(tsc
), 1, fp
);
1022 /* Read process state from a file */
1024 /* Called because a HDR_PROCESS was found */
1025 static void read_process_state_raw(LttvTraceState
*self
, FILE *fp
,
1026 GPtrArray
*quarktable
)
1028 LttvExecutionState
*es
;
1029 LttvProcessState
*process
, *parent_process
;
1030 LttvProcessState tmp
;
1035 /* TODO : check return value */
1036 fread(&tmp
.type
, sizeof(tmp
.type
), 1, fp
);
1037 fread(&tmp
.name
, sizeof(tmp
.name
), 1, fp
);
1038 fread(&tmp
.brand
, sizeof(tmp
.brand
), 1, fp
);
1039 fread(&tmp
.pid
, sizeof(tmp
.pid
), 1, fp
);
1040 fread(&tmp
.free_events
, sizeof(tmp
.free_events
), 1, fp
);
1041 fread(&tmp
.tgid
, sizeof(tmp
.tgid
), 1, fp
);
1042 fread(&tmp
.ppid
, sizeof(tmp
.ppid
), 1, fp
);
1043 fread(&tmp
.cpu
, sizeof(tmp
.cpu
), 1, fp
);
1044 fread(&tmp
.creation_time
, sizeof(tmp
.creation_time
), 1, fp
);
1045 fread(&tmp
.insertion_time
, sizeof(tmp
.insertion_time
), 1, fp
);
1048 process
= lttv_state_find_process(self
, tmp
.cpu
, tmp
.pid
);
1050 /* We must link to the parent */
1051 parent_process
= lttv_state_find_process_or_create(self
, ANY_CPU
, tmp
.ppid
,
1053 process
= lttv_state_find_process(self
, ANY_CPU
, tmp
.pid
);
1054 if(process
== NULL
) {
1055 process
= lttv_state_create_process(self
, parent_process
, tmp
.cpu
,
1057 g_quark_from_string((gchar
*)g_ptr_array_index(quarktable
, tmp
.name
)),
1058 &tmp
.creation_time
);
1061 process
->insertion_time
= tmp
.insertion_time
;
1062 process
->creation_time
= tmp
.creation_time
;
1063 process
->type
= g_quark_from_string(
1064 (gchar
*)g_ptr_array_index(quarktable
, tmp
.type
));
1065 process
->tgid
= tmp
.tgid
;
1066 process
->ppid
= tmp
.ppid
;
1067 process
->brand
= g_quark_from_string(
1068 (gchar
*)g_ptr_array_index(quarktable
, tmp
.brand
));
1070 g_quark_from_string((gchar
*)g_ptr_array_index(quarktable
, tmp
.name
));
1071 process
->free_events
= tmp
.free_events
;
1074 if(feof(fp
) || ferror(fp
)) goto end_loop
;
1076 gint hdr
= fgetc(fp
);
1077 if(hdr
== EOF
) goto end_loop
;
1081 process
->execution_stack
=
1082 g_array_set_size(process
->execution_stack
,
1083 process
->execution_stack
->len
+ 1);
1084 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
1085 process
->execution_stack
->len
-1);
1086 process
->state
= es
;
1088 fread(&es
->t
, sizeof(es
->t
), 1, fp
);
1089 es
->t
= g_quark_from_string(
1090 (gchar
*)g_ptr_array_index(quarktable
, es
->t
));
1091 fread(&es
->n
, sizeof(es
->n
), 1, fp
);
1092 es
->n
= g_quark_from_string(
1093 (gchar
*)g_ptr_array_index(quarktable
, es
->n
));
1094 fread(&es
->s
, sizeof(es
->s
), 1, fp
);
1095 es
->s
= g_quark_from_string(
1096 (gchar
*)g_ptr_array_index(quarktable
, es
->s
));
1097 fread(&es
->entry
, sizeof(es
->entry
), 1, fp
);
1098 fread(&es
->change
, sizeof(es
->change
), 1, fp
);
1099 fread(&es
->cum_cpu_time
, sizeof(es
->cum_cpu_time
), 1, fp
);
1101 case HDR_USER_STACK
:
1102 process
->user_stack
= g_array_set_size(process
->user_stack
,
1103 process
->user_stack
->len
+ 1);
1104 address
= &g_array_index(process
->user_stack
, guint64
,
1105 process
->user_stack
->len
-1);
1106 fread(address
, sizeof(address
), 1, fp
);
1107 process
->current_function
= *address
;
1110 fread(&tmpq
, sizeof(tmpq
), 1, fp
);
1111 fread(&process
->usertrace
->cpu
, sizeof(process
->usertrace
->cpu
), 1, fp
);
1123 /* Called because a HDR_PROCESS_STATE was found */
1124 /* Append a saved state to the trace states */
1125 void lttv_state_read_raw(LttvTraceState
*self
, FILE *fp
, GPtrArray
*quarktable
)
1127 guint i
, nb_tracefile
, nb_block
, offset
;
1129 LttvTracefileState
*tfcs
;
1131 LttEventPosition
*ep
;
1139 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
1141 LttvAttributeValue value
;
1142 GTree
*pqueue
= self
->parent
.ts_context
->pqueue
;
1143 ep
= ltt_event_position_new();
1145 restore_init_state(self
);
1147 fread(&t
, sizeof(t
), 1, fp
);
1150 if(feof(fp
) || ferror(fp
)) goto end_loop
;
1152 if(hdr
== EOF
) goto end_loop
;
1156 /* Call read_process_state_raw */
1157 read_process_state_raw(self
, fp
, quarktable
);
1165 case HDR_USER_STACK
:
1167 case HDR_PROCESS_STATE
:
1173 g_error("Error while parsing saved state file : unknown data header %d",
1179 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
1180 for(i
=0;i
<nb_cpus
;i
++) {
1183 g_assert(hdr
== HDR_CPU
);
1184 fread(&cpu_num
, sizeof(cpu_num
), 1, fp
); /* cpu number */
1185 g_assert(i
== cpu_num
);
1186 fread(&self
->running_process
[i
]->pid
,
1187 sizeof(self
->running_process
[i
]->pid
), 1, fp
);
1190 nb_tracefile
= self
->parent
.tracefiles
->len
;
1192 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1194 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1195 LttvTracefileContext
*, i
));
1196 // fprintf(fp, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
1197 // tfcs->parent.timestamp.tv_sec,
1198 // tfcs->parent.timestamp.tv_nsec);
1199 g_tree_remove(pqueue
, &tfcs
->parent
);
1201 g_assert(hdr
== HDR_TRACEFILE
);
1202 fread(&tfcs
->parent
.timestamp
, sizeof(tfcs
->parent
.timestamp
), 1, fp
);
1203 /* Note : if timestamp if LTT_TIME_INFINITE, there will be no
1204 * position following : end of trace */
1205 if(ltt_time_compare(tfcs
->parent
.timestamp
, ltt_time_infinite
) != 0) {
1206 fread(&nb_block
, sizeof(nb_block
), 1, fp
);
1207 fread(&offset
, sizeof(offset
), 1, fp
);
1208 fread(&tsc
, sizeof(tsc
), 1, fp
);
1209 ltt_event_position_set(ep
, tfcs
->parent
.tf
, nb_block
, offset
, tsc
);
1210 gint ret
= ltt_tracefile_seek_position(tfcs
->parent
.tf
, ep
);
1212 g_tree_insert(pqueue
, &tfcs
->parent
, &tfcs
->parent
);
1217 saved_states_tree
= lttv_attribute_find_subdir(self
->parent
.t_a
,
1218 LTTV_STATE_SAVED_STATES
);
1219 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1220 value
= lttv_attribute_add(saved_states_tree
,
1221 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
1222 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
1223 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
1224 *(value
.v_time
) = t
;
1225 lttv_state_save(self
, saved_state_tree
);
1226 g_debug("Saving state at time %lu.%lu", t
.tv_sec
,
1229 *(self
->max_time_state_recomputed_in_seek
) = t
;
1233 /* Called when a HDR_TRACE is found */
1234 void lttv_trace_states_read_raw(LttvTraceState
*tcs
, FILE *fp
,
1235 GPtrArray
*quarktable
)
1240 if(feof(fp
) || ferror(fp
)) goto end_loop
;
1242 if(hdr
== EOF
) goto end_loop
;
1245 case HDR_PROCESS_STATE
:
1246 /* Call read_process_state_raw */
1247 lttv_state_read_raw(tcs
, fp
, quarktable
);
1255 case HDR_USER_STACK
:
1259 g_error("Error while parsing saved state file :"
1260 " unexpected data header %d",
1264 g_error("Error while parsing saved state file : unknown data header %d",
1269 *(tcs
->max_time_state_recomputed_in_seek
) = tcs
->parent
.time_span
.end_time
;
1270 restore_init_state(tcs
);
1271 lttv_process_trace_seek_time(&tcs
->parent
, ltt_time_zero
);
1277 /* Copy each process from an existing hash table to a new one */
1279 static void copy_process_state(gpointer key
, gpointer value
,gpointer user_data
)
1281 LttvProcessState
*process
, *new_process
;
1283 GHashTable
*new_processes
= (GHashTable
*)user_data
;
1287 process
= (LttvProcessState
*)value
;
1288 new_process
= g_new(LttvProcessState
, 1);
1289 *new_process
= *process
;
1290 new_process
->execution_stack
= g_array_sized_new(FALSE
, FALSE
,
1291 sizeof(LttvExecutionState
), PREALLOCATED_EXECUTION_STACK
);
1292 new_process
->execution_stack
=
1293 g_array_set_size(new_process
->execution_stack
,
1294 process
->execution_stack
->len
);
1295 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
1296 g_array_index(new_process
->execution_stack
, LttvExecutionState
, i
) =
1297 g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
1299 new_process
->state
= &g_array_index(new_process
->execution_stack
,
1300 LttvExecutionState
, new_process
->execution_stack
->len
- 1);
1301 new_process
->user_stack
= g_array_sized_new(FALSE
, FALSE
,
1302 sizeof(guint64
), 0);
1303 new_process
->user_stack
=
1304 g_array_set_size(new_process
->user_stack
,
1305 process
->user_stack
->len
);
1306 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
1307 g_array_index(new_process
->user_stack
, guint64
, i
) =
1308 g_array_index(process
->user_stack
, guint64
, i
);
1310 new_process
->current_function
= process
->current_function
;
1311 g_hash_table_insert(new_processes
, new_process
, new_process
);
1315 static GHashTable
*lttv_state_copy_process_table(GHashTable
*processes
)
1317 GHashTable
*new_processes
= g_hash_table_new(process_hash
, process_equal
);
1319 g_hash_table_foreach(processes
, copy_process_state
, new_processes
);
1320 return new_processes
;
1323 static LttvCPUState
*lttv_state_copy_cpu_states(LttvCPUState
*states
, guint n
)
1326 LttvCPUState
*retval
;
1328 retval
= g_new(LttvCPUState
, n
);
1330 for(i
=0; i
<n
; i
++) {
1331 retval
[i
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvCPUMode
));
1332 retval
[i
].last_irq
= states
[i
].last_irq
;
1333 retval
[i
].last_soft_irq
= states
[i
].last_soft_irq
;
1334 retval
[i
].last_trap
= states
[i
].last_trap
;
1335 g_array_set_size(retval
[i
].mode_stack
, states
[i
].mode_stack
->len
);
1336 for(j
=0; j
<states
[i
].mode_stack
->len
; j
++) {
1337 g_array_index(retval
[i
].mode_stack
, GQuark
, j
) = g_array_index(states
[i
].mode_stack
, GQuark
, j
);
1344 static void lttv_state_free_cpu_states(LttvCPUState
*states
, guint n
)
1348 for(i
=0; i
<n
; i
++) {
1349 g_array_free(states
[i
].mode_stack
, TRUE
);
1355 static LttvIRQState
*lttv_state_copy_irq_states(LttvIRQState
*states
, guint n
)
1358 LttvIRQState
*retval
;
1360 retval
= g_new(LttvIRQState
, n
);
1362 for(i
=0; i
<n
; i
++) {
1363 retval
[i
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvIRQMode
));
1364 g_array_set_size(retval
[i
].mode_stack
, states
[i
].mode_stack
->len
);
1365 for(j
=0; j
<states
[i
].mode_stack
->len
; j
++) {
1366 g_array_index(retval
[i
].mode_stack
, GQuark
, j
) = g_array_index(states
[i
].mode_stack
, GQuark
, j
);
1373 static void lttv_state_free_irq_states(LttvIRQState
*states
, guint n
)
1377 for(i
=0; i
<n
; i
++) {
1378 g_array_free(states
[i
].mode_stack
, TRUE
);
1384 static LttvSoftIRQState
*lttv_state_copy_soft_irq_states(LttvSoftIRQState
*states
, guint n
)
1387 LttvSoftIRQState
*retval
;
1389 retval
= g_new(LttvSoftIRQState
, n
);
1391 for(i
=0; i
<n
; i
++) {
1392 retval
[i
].pending
= states
[i
].pending
;
1393 retval
[i
].running
= states
[i
].running
;
1399 static void lttv_state_free_soft_irq_states(LttvSoftIRQState
*states
, guint n
)
1404 static LttvTrapState
*lttv_state_copy_trap_states(LttvTrapState
*states
, guint n
)
1407 LttvTrapState
*retval
;
1409 retval
= g_new(LttvTrapState
, n
);
1411 for(i
=0; i
<n
; i
++) {
1412 retval
[i
].running
= states
[i
].running
;
1418 static void lttv_state_free_trap_states(LttvTrapState
*states
, guint n
)
1423 /* bdevstate stuff */
1425 static LttvBdevState
*get_hashed_bdevstate(LttvTraceState
*ts
, guint16 devcode
)
1427 gint devcode_gint
= devcode
;
1428 gpointer bdev
= g_hash_table_lookup(ts
->bdev_states
, &devcode_gint
);
1430 LttvBdevState
*bdevstate
= g_new(LttvBdevState
, 1);
1431 bdevstate
->mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(GQuark
));
1433 gint
* key
= g_new(gint
, 1);
1435 g_hash_table_insert(ts
->bdev_states
, key
, bdevstate
);
1443 static LttvBdevState
*bdevstate_new(void)
1445 LttvBdevState
*retval
;
1446 retval
= g_new(LttvBdevState
, 1);
1447 retval
->mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(GQuark
));
1452 static void bdevstate_free(LttvBdevState
*bds
)
1454 g_array_free(bds
->mode_stack
, TRUE
);
1458 static void bdevstate_free_cb(gpointer key
, gpointer value
, gpointer user_data
)
1460 LttvBdevState
*bds
= (LttvBdevState
*) value
;
1462 bdevstate_free(bds
);
1465 static LttvBdevState
*bdevstate_copy(LttvBdevState
*bds
)
1467 LttvBdevState
*retval
;
1469 retval
= bdevstate_new();
1470 g_array_insert_vals(retval
->mode_stack
, 0, bds
->mode_stack
->data
, bds
->mode_stack
->len
);
1475 static void insert_and_copy_bdev_state(gpointer k
, gpointer v
, gpointer u
)
1477 //GHashTable *ht = (GHashTable *)u;
1478 LttvBdevState
*bds
= (LttvBdevState
*)v
;
1479 LttvBdevState
*newbds
;
1481 newbds
= bdevstate_copy(bds
);
1483 g_hash_table_insert(u
, k
, newbds
);
1486 static GHashTable
*lttv_state_copy_blkdev_hashtable(GHashTable
*ht
)
1490 retval
= g_hash_table_new(g_int_hash
, g_int_equal
);
1492 g_hash_table_foreach(ht
, insert_and_copy_bdev_state
, retval
);
1497 /* Free a hashtable and the LttvBdevState structures its values
1500 static void lttv_state_free_blkdev_hashtable(GHashTable
*ht
)
1502 g_hash_table_foreach(ht
, bdevstate_free_cb
, NULL
);
1503 g_hash_table_destroy(ht
);
1506 /* The saved state for each trace contains a member "processes", which
1507 stores a copy of the process table, and a member "tracefiles" with
1508 one entry per tracefile. Each tracefile has a "process" member pointing
1509 to the current process and a "position" member storing the tracefile
1510 position (needed to seek to the current "next" event. */
1512 static void state_save(LttvTraceState
*self
, LttvAttribute
*container
)
1514 guint i
, nb_tracefile
, nb_cpus
, nb_irqs
, nb_soft_irqs
, nb_traps
;
1516 LttvTracefileState
*tfcs
;
1518 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
1520 guint
*running_process
;
1522 LttvAttributeValue value
;
1524 LttEventPosition
*ep
;
1526 tracefiles_tree
= lttv_attribute_find_subdir(container
,
1527 LTTV_STATE_TRACEFILES
);
1529 value
= lttv_attribute_add(container
, LTTV_STATE_PROCESSES
,
1531 *(value
.v_pointer
) = lttv_state_copy_process_table(self
->processes
);
1533 /* Add the currently running processes array */
1534 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
1535 running_process
= g_new(guint
, nb_cpus
);
1536 for(i
=0;i
<nb_cpus
;i
++) {
1537 running_process
[i
] = self
->running_process
[i
]->pid
;
1539 value
= lttv_attribute_add(container
, LTTV_STATE_RUNNING_PROCESS
,
1541 *(value
.v_pointer
) = running_process
;
1543 g_info("State save");
1545 nb_tracefile
= self
->parent
.tracefiles
->len
;
1547 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1549 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1550 LttvTracefileContext
*, i
));
1551 tracefile_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1552 value
= lttv_attribute_add(tracefiles_tree
, i
,
1554 *(value
.v_gobject
) = (GObject
*)tracefile_tree
;
1556 value
= lttv_attribute_add(tracefile_tree
, LTTV_STATE_PROCESS
,
1558 *(value
.v_uint
) = tfcs
->process
->pid
;
1560 value
= lttv_attribute_add(tracefile_tree
, LTTV_STATE_EVENT
,
1562 /* Only save the position if the tfs has not infinite time. */
1563 //if(!g_tree_lookup(self->parent.ts_context->pqueue, &tfcs->parent)
1564 // && current_tfcs != tfcs) {
1565 if(ltt_time_compare(tfcs
->parent
.timestamp
, ltt_time_infinite
) == 0) {
1566 *(value
.v_pointer
) = NULL
;
1568 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
1569 ep
= ltt_event_position_new();
1570 ltt_event_position(e
, ep
);
1571 *(value
.v_pointer
) = ep
;
1573 guint nb_block
, offset
;
1576 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
1577 g_info("Block %u offset %u tsc %" PRIu64
" time %lu.%lu", nb_block
, offset
,
1579 tfcs
->parent
.timestamp
.tv_sec
, tfcs
->parent
.timestamp
.tv_nsec
);
1583 /* save the cpu state */
1585 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_CPUS_COUNT
,
1587 *(value
.v_uint
) = nb_cpus
;
1589 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_CPUS
,
1591 *(value
.v_pointer
) = lttv_state_copy_cpu_states(self
->cpu_states
, nb_cpus
);
1594 /* save the irq state */
1595 nb_irqs
= self
->nb_irqs
;
1597 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_IRQS
,
1599 *(value
.v_pointer
) = lttv_state_copy_irq_states(self
->irq_states
, nb_irqs
);
1602 /* save the soft irq state */
1603 nb_soft_irqs
= self
->nb_soft_irqs
;
1605 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_SOFT_IRQS
,
1607 *(value
.v_pointer
) = lttv_state_copy_soft_irq_states(self
->soft_irq_states
, nb_soft_irqs
);
1610 /* save the trap state */
1611 nb_traps
= self
->nb_traps
;
1613 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_TRAPS
,
1615 *(value
.v_pointer
) = lttv_state_copy_trap_states(self
->trap_states
, nb_traps
);
1618 /* save the blkdev states */
1619 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_BLKDEVS
,
1621 *(value
.v_pointer
) = lttv_state_copy_blkdev_hashtable(self
->bdev_states
);
1625 static void state_restore(LttvTraceState
*self
, LttvAttribute
*container
)
1627 guint i
, nb_tracefile
, pid
, nb_cpus
, nb_irqs
, nb_soft_irqs
, nb_traps
;
1629 LttvTracefileState
*tfcs
;
1631 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
1633 guint
*running_process
;
1635 LttvAttributeType type
;
1637 LttvAttributeValue value
;
1639 LttvAttributeName name
;
1643 LttEventPosition
*ep
;
1645 LttvTracesetContext
*tsc
= self
->parent
.ts_context
;
1647 tracefiles_tree
= lttv_attribute_find_subdir(container
,
1648 LTTV_STATE_TRACEFILES
);
1650 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_PROCESSES
,
1652 g_assert(type
== LTTV_POINTER
);
1653 lttv_state_free_process_table(self
->processes
);
1654 self
->processes
= lttv_state_copy_process_table(*(value
.v_pointer
));
1656 /* Add the currently running processes array */
1657 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
1658 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RUNNING_PROCESS
,
1660 g_assert(type
== LTTV_POINTER
);
1661 running_process
= *(value
.v_pointer
);
1662 for(i
=0;i
<nb_cpus
;i
++) {
1663 pid
= running_process
[i
];
1664 self
->running_process
[i
] = lttv_state_find_process(self
, i
, pid
);
1665 g_assert(self
->running_process
[i
] != NULL
);
1668 nb_tracefile
= self
->parent
.tracefiles
->len
;
1670 //g_tree_destroy(tsc->pqueue);
1671 //tsc->pqueue = g_tree_new(compare_tracefile);
1673 /* restore cpu resource states */
1674 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS
, &value
);
1675 g_assert(type
== LTTV_POINTER
);
1676 lttv_state_free_cpu_states(self
->cpu_states
, nb_cpus
);
1677 self
->cpu_states
= lttv_state_copy_cpu_states(*(value
.v_pointer
), nb_cpus
);
1679 /* restore irq resource states */
1680 nb_irqs
= self
->nb_irqs
;
1681 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_IRQS
, &value
);
1682 g_assert(type
== LTTV_POINTER
);
1683 lttv_state_free_irq_states(self
->irq_states
, nb_irqs
);
1684 self
->irq_states
= lttv_state_copy_irq_states(*(value
.v_pointer
), nb_irqs
);
1686 /* restore soft irq resource states */
1687 nb_soft_irqs
= self
->nb_soft_irqs
;
1688 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_SOFT_IRQS
, &value
);
1689 g_assert(type
== LTTV_POINTER
);
1690 lttv_state_free_soft_irq_states(self
->soft_irq_states
, nb_soft_irqs
);
1691 self
->soft_irq_states
= lttv_state_copy_soft_irq_states(*(value
.v_pointer
), nb_soft_irqs
);
1693 /* restore trap resource states */
1694 nb_traps
= self
->nb_traps
;
1695 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_TRAPS
, &value
);
1696 g_assert(type
== LTTV_POINTER
);
1697 lttv_state_free_trap_states(self
->trap_states
, nb_traps
);
1698 self
->trap_states
= lttv_state_copy_trap_states(*(value
.v_pointer
), nb_traps
);
1700 /* restore the blkdev states */
1701 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_BLKDEVS
, &value
);
1702 g_assert(type
== LTTV_POINTER
);
1703 lttv_state_free_blkdev_hashtable(self
->bdev_states
);
1704 self
->bdev_states
= lttv_state_copy_blkdev_hashtable(*(value
.v_pointer
));
1706 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1708 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1709 LttvTracefileContext
*, i
));
1710 type
= lttv_attribute_get(tracefiles_tree
, i
, &name
, &value
, &is_named
);
1711 g_assert(type
== LTTV_GOBJECT
);
1712 tracefile_tree
= *((LttvAttribute
**)(value
.v_gobject
));
1714 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_PROCESS
,
1716 g_assert(type
== LTTV_UINT
);
1717 pid
= *(value
.v_uint
);
1718 tfcs
->process
= lttv_state_find_process_or_create(tfcs
, pid
);
1720 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_EVENT
,
1722 g_assert(type
== LTTV_POINTER
);
1723 //g_assert(*(value.v_pointer) != NULL);
1724 ep
= *(value
.v_pointer
);
1725 g_assert(tfcs
->parent
.t_context
!= NULL
);
1727 tfcs
->cpu_state
= &self
->cpu_states
[tfcs
->cpu
];
1729 LttvTracefileContext
*tfc
= LTTV_TRACEFILE_CONTEXT(tfcs
);
1730 g_tree_remove(tsc
->pqueue
, tfc
);
1733 g_assert(ltt_tracefile_seek_position(tfc
->tf
, ep
) == 0);
1734 tfc
->timestamp
= ltt_event_time(ltt_tracefile_get_event(tfc
->tf
));
1735 g_assert(ltt_time_compare(tfc
->timestamp
, ltt_time_infinite
) != 0);
1736 g_tree_insert(tsc
->pqueue
, tfc
, tfc
);
1737 g_info("Restoring state for a tf at time %lu.%lu", tfc
->timestamp
.tv_sec
, tfc
->timestamp
.tv_nsec
);
1739 tfc
->timestamp
= ltt_time_infinite
;
1745 static void state_saved_free(LttvTraceState
*self
, LttvAttribute
*container
)
1747 guint i
, nb_tracefile
, nb_cpus
, nb_irqs
, nb_softirqs
;
1749 LttvTracefileState
*tfcs
;
1751 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
1753 guint
*running_process
;
1755 LttvAttributeType type
;
1757 LttvAttributeValue value
;
1759 LttvAttributeName name
;
1763 tracefiles_tree
= lttv_attribute_find_subdir(container
,
1764 LTTV_STATE_TRACEFILES
);
1765 g_object_ref(G_OBJECT(tracefiles_tree
));
1766 lttv_attribute_remove_by_name(container
, LTTV_STATE_TRACEFILES
);
1768 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_PROCESSES
,
1770 g_assert(type
== LTTV_POINTER
);
1771 lttv_state_free_process_table(*(value
.v_pointer
));
1772 *(value
.v_pointer
) = NULL
;
1773 lttv_attribute_remove_by_name(container
, LTTV_STATE_PROCESSES
);
1775 /* Free running processes array */
1776 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RUNNING_PROCESS
,
1778 g_assert(type
== LTTV_POINTER
);
1779 running_process
= *(value
.v_pointer
);
1780 g_free(running_process
);
1782 /* free cpu resource states */
1783 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS_COUNT
, &value
);
1784 g_assert(type
== LTTV_UINT
);
1785 nb_cpus
= *value
.v_uint
;
1786 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS
, &value
);
1787 g_assert(type
== LTTV_POINTER
);
1788 lttv_state_free_cpu_states(*(value
.v_pointer
), nb_cpus
);
1790 /* free irq resource states */
1791 nb_irqs
= self
->nb_irqs
;
1792 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_IRQS
, &value
);
1793 g_assert(type
== LTTV_POINTER
);
1794 lttv_state_free_irq_states(*(value
.v_pointer
), nb_irqs
);
1796 /* free softirq resource states */
1797 nb_softirqs
= self
->nb_irqs
;
1798 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_SOFT_IRQS
, &value
);
1799 g_assert(type
== LTTV_POINTER
);
1800 lttv_state_free_soft_irq_states(*(value
.v_pointer
), nb_softirqs
);
1802 /* free the blkdev states */
1803 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_BLKDEVS
, &value
);
1804 g_assert(type
== LTTV_POINTER
);
1805 lttv_state_free_blkdev_hashtable(*(value
.v_pointer
));
1807 nb_tracefile
= self
->parent
.tracefiles
->len
;
1809 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1811 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1812 LttvTracefileContext
*, i
));
1813 type
= lttv_attribute_get(tracefiles_tree
, i
, &name
, &value
, &is_named
);
1814 g_assert(type
== LTTV_GOBJECT
);
1815 tracefile_tree
= *((LttvAttribute
**)(value
.v_gobject
));
1817 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_EVENT
,
1819 g_assert(type
== LTTV_POINTER
);
1820 if(*(value
.v_pointer
) != NULL
) g_free(*(value
.v_pointer
));
1822 g_object_unref(G_OBJECT(tracefiles_tree
));
1826 static void free_saved_state(LttvTraceState
*self
)
1830 LttvAttributeType type
;
1832 LttvAttributeValue value
;
1834 LttvAttributeName name
;
1838 LttvAttribute
*saved_states
;
1840 saved_states
= lttv_attribute_find_subdir(self
->parent
.t_a
,
1841 LTTV_STATE_SAVED_STATES
);
1843 nb
= lttv_attribute_get_number(saved_states
);
1844 for(i
= 0 ; i
< nb
; i
++) {
1845 type
= lttv_attribute_get(saved_states
, i
, &name
, &value
, &is_named
);
1846 g_assert(type
== LTTV_GOBJECT
);
1847 state_saved_free(self
, *((LttvAttribute
**)value
.v_gobject
));
1850 lttv_attribute_remove_by_name(self
->parent
.t_a
, LTTV_STATE_SAVED_STATES
);
1855 create_max_time(LttvTraceState
*tcs
)
1857 LttvAttributeValue v
;
1859 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
1861 g_assert(*(v
.v_pointer
) == NULL
);
1862 *(v
.v_pointer
) = g_new(LttTime
,1);
1863 *((LttTime
*)*(v
.v_pointer
)) = ltt_time_zero
;
1868 get_max_time(LttvTraceState
*tcs
)
1870 LttvAttributeValue v
;
1872 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
1874 g_assert(*(v
.v_pointer
) != NULL
);
1875 tcs
->max_time_state_recomputed_in_seek
= (LttTime
*)*(v
.v_pointer
);
1880 free_max_time(LttvTraceState
*tcs
)
1882 LttvAttributeValue v
;
1884 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
1886 g_free(*(v
.v_pointer
));
1887 *(v
.v_pointer
) = NULL
;
1891 typedef struct _LttvNameTables
{
1892 // FIXME GQuark *eventtype_names;
1893 GQuark
*syscall_names
;
1899 GQuark
*soft_irq_names
;
1901 GHashTable
*kprobe_hash
;
1906 create_name_tables(LttvTraceState
*tcs
)
1910 GString
*fe_name
= g_string_new("");
1912 LttvNameTables
*name_tables
= g_new(LttvNameTables
, 1);
1914 LttvAttributeValue v
;
1918 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_NAME_TABLES
,
1920 g_assert(*(v
.v_pointer
) == NULL
);
1921 *(v
.v_pointer
) = name_tables
;
1923 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 1);
1925 if(!lttv_trace_find_hook(tcs
->parent
.t
,
1927 LTT_EVENT_SYSCALL_ENTRY
,
1928 FIELD_ARRAY(LTT_FIELD_SYSCALL_ID
),
1929 NULL
, NULL
, &hooks
)) {
1931 // th = lttv_trace_hook_get_first(&th);
1933 // t = ltt_field_type(lttv_trace_get_hook_field(th, 0));
1934 // nb = ltt_type_element_number(t);
1936 // name_tables->syscall_names = g_new(GQuark, nb);
1937 // name_tables->nb_syscalls = nb;
1939 // for(i = 0 ; i < nb ; i++) {
1940 // name_tables->syscall_names[i] = ltt_enum_string_get(t, i);
1941 // if(!name_tables->syscall_names[i]) {
1942 // GString *string = g_string_new("");
1943 // g_string_printf(string, "syscall %u", i);
1944 // name_tables->syscall_names[i] = g_quark_from_string(string->str);
1945 // g_string_free(string, TRUE);
1949 name_tables
->nb_syscalls
= 256;
1950 name_tables
->syscall_names
= g_new(GQuark
, 256);
1951 for(i
= 0 ; i
< 256 ; i
++) {
1952 g_string_printf(fe_name
, "syscall %d", i
);
1953 name_tables
->syscall_names
[i
] = g_quark_from_string(fe_name
->str
);
1956 name_tables
->syscall_names
= NULL
;
1957 name_tables
->nb_syscalls
= 0;
1959 lttv_trace_hook_remove_all(&hooks
);
1961 if(!lttv_trace_find_hook(tcs
->parent
.t
,
1963 LTT_EVENT_TRAP_ENTRY
,
1964 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
1965 NULL
, NULL
, &hooks
)) {
1967 // th = lttv_trace_hook_get_first(&th);
1969 // t = ltt_field_type(lttv_trace_get_hook_field(th, 0));
1970 // //nb = ltt_type_element_number(t);
1972 // name_tables->trap_names = g_new(GQuark, nb);
1973 // for(i = 0 ; i < nb ; i++) {
1974 // name_tables->trap_names[i] = g_quark_from_string(
1975 // ltt_enum_string_get(t, i));
1978 name_tables
->nb_traps
= 256;
1979 name_tables
->trap_names
= g_new(GQuark
, 256);
1980 for(i
= 0 ; i
< 256 ; i
++) {
1981 g_string_printf(fe_name
, "trap %d", i
);
1982 name_tables
->trap_names
[i
] = g_quark_from_string(fe_name
->str
);
1985 name_tables
->trap_names
= NULL
;
1986 name_tables
->nb_traps
= 0;
1988 lttv_trace_hook_remove_all(&hooks
);
1990 if(!lttv_trace_find_hook(tcs
->parent
.t
,
1992 LTT_EVENT_IRQ_ENTRY
,
1993 FIELD_ARRAY(LTT_FIELD_IRQ_ID
),
1994 NULL
, NULL
, &hooks
)) {
1997 name_tables->irq_names = g_new(GQuark, nb);
1998 for(i = 0 ; i < nb ; i++) {
1999 name_tables->irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
2003 name_tables
->nb_irqs
= 256;
2004 name_tables
->irq_names
= g_new(GQuark
, 256);
2005 for(i
= 0 ; i
< 256 ; i
++) {
2006 g_string_printf(fe_name
, "irq %d", i
);
2007 name_tables
->irq_names
[i
] = g_quark_from_string(fe_name
->str
);
2010 name_tables
->nb_irqs
= 0;
2011 name_tables
->irq_names
= NULL
;
2013 lttv_trace_hook_remove_all(&hooks
);
2015 name_tables->soft_irq_names = g_new(GQuark, nb);
2016 for(i = 0 ; i < nb ; i++) {
2017 name_tables->soft_irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
2021 /* the kernel is limited to 32 statically defined softirqs */
2022 name_tables
->nb_softirqs
= 32;
2023 name_tables
->soft_irq_names
= g_new(GQuark
, name_tables
->nb_softirqs
);
2024 for(i
= 0 ; i
< name_tables
->nb_softirqs
; i
++) {
2025 g_string_printf(fe_name
, "softirq %d", i
);
2026 name_tables
->soft_irq_names
[i
] = g_quark_from_string(fe_name
->str
);
2028 g_array_free(hooks
, TRUE
);
2030 g_string_free(fe_name
, TRUE
);
2032 #if (__SIZEOF_LONG__ == 4)
2033 name_tables
->kprobe_hash
= g_hash_table_new_full(guint64_hash
, guint64_equal
,
2036 name_tables
->kprobe_hash
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
2042 get_name_tables(LttvTraceState
*tcs
)
2044 LttvNameTables
*name_tables
;
2046 LttvAttributeValue v
;
2048 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_NAME_TABLES
,
2050 g_assert(*(v
.v_pointer
) != NULL
);
2051 name_tables
= (LttvNameTables
*)*(v
.v_pointer
);
2052 //tcs->eventtype_names = name_tables->eventtype_names;
2053 tcs
->syscall_names
= name_tables
->syscall_names
;
2054 tcs
->nb_syscalls
= name_tables
->nb_syscalls
;
2055 tcs
->trap_names
= name_tables
->trap_names
;
2056 tcs
->nb_traps
= name_tables
->nb_traps
;
2057 tcs
->irq_names
= name_tables
->irq_names
;
2058 tcs
->soft_irq_names
= name_tables
->soft_irq_names
;
2059 tcs
->nb_irqs
= name_tables
->nb_irqs
;
2060 tcs
->nb_soft_irqs
= name_tables
->nb_softirqs
;
2061 tcs
->kprobe_hash
= name_tables
->kprobe_hash
;
2066 free_name_tables(LttvTraceState
*tcs
)
2068 LttvNameTables
*name_tables
;
2070 LttvAttributeValue v
;
2072 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_NAME_TABLES
,
2074 name_tables
= (LttvNameTables
*)*(v
.v_pointer
);
2075 *(v
.v_pointer
) = NULL
;
2077 // g_free(name_tables->eventtype_names);
2078 if(name_tables
->syscall_names
) g_free(name_tables
->syscall_names
);
2079 if(name_tables
->trap_names
) g_free(name_tables
->trap_names
);
2080 if(name_tables
->irq_names
) g_free(name_tables
->irq_names
);
2081 if(name_tables
->soft_irq_names
) g_free(name_tables
->soft_irq_names
);
2082 if(name_tables
) g_free(name_tables
);
2083 if(name_tables
) g_hash_table_destroy(name_tables
->kprobe_hash
);
2086 #ifdef HASH_TABLE_DEBUG
2088 static void test_process(gpointer key
, gpointer value
, gpointer user_data
)
2090 LttvProcessState
*process
= (LttvProcessState
*)value
;
2092 /* Test for process corruption */
2093 guint stack_len
= process
->execution_stack
->len
;
2096 static void hash_table_check(GHashTable
*table
)
2098 g_hash_table_foreach(table
, test_process
, NULL
);
2104 /* clears the stack and sets the state passed as argument */
2105 static void cpu_set_base_mode(LttvCPUState
*cpust
, LttvCPUMode state
)
2107 g_array_set_size(cpust
->mode_stack
, 1);
2108 ((GQuark
*)cpust
->mode_stack
->data
)[0] = state
;
2111 static void cpu_push_mode(LttvCPUState
*cpust
, LttvCPUMode state
)
2113 g_array_set_size(cpust
->mode_stack
, cpust
->mode_stack
->len
+ 1);
2114 ((GQuark
*)cpust
->mode_stack
->data
)[cpust
->mode_stack
->len
- 1] = state
;
2117 static void cpu_pop_mode(LttvCPUState
*cpust
)
2119 if(cpust
->mode_stack
->len
<= 1)
2120 cpu_set_base_mode(cpust
, LTTV_CPU_UNKNOWN
);
2122 g_array_set_size(cpust
->mode_stack
, cpust
->mode_stack
->len
- 1);
2125 /* clears the stack and sets the state passed as argument */
2126 static void bdev_set_base_mode(LttvBdevState
*bdevst
, LttvBdevMode state
)
2128 g_array_set_size(bdevst
->mode_stack
, 1);
2129 ((GQuark
*)bdevst
->mode_stack
->data
)[0] = state
;
2132 static void bdev_push_mode(LttvBdevState
*bdevst
, LttvBdevMode state
)
2134 g_array_set_size(bdevst
->mode_stack
, bdevst
->mode_stack
->len
+ 1);
2135 ((GQuark
*)bdevst
->mode_stack
->data
)[bdevst
->mode_stack
->len
- 1] = state
;
2138 static void bdev_pop_mode(LttvBdevState
*bdevst
)
2140 if(bdevst
->mode_stack
->len
<= 1)
2141 bdev_set_base_mode(bdevst
, LTTV_BDEV_UNKNOWN
);
2143 g_array_set_size(bdevst
->mode_stack
, bdevst
->mode_stack
->len
- 1);
2146 static void irq_set_base_mode(LttvIRQState
*irqst
, LttvIRQMode state
)
2148 g_array_set_size(irqst
->mode_stack
, 1);
2149 ((GQuark
*)irqst
->mode_stack
->data
)[0] = state
;
2152 static void irq_push_mode(LttvIRQState
*irqst
, LttvIRQMode state
)
2154 g_array_set_size(irqst
->mode_stack
, irqst
->mode_stack
->len
+ 1);
2155 ((GQuark
*)irqst
->mode_stack
->data
)[irqst
->mode_stack
->len
- 1] = state
;
2158 static void irq_pop_mode(LttvIRQState
*irqst
)
2160 if(irqst
->mode_stack
->len
<= 1)
2161 irq_set_base_mode(irqst
, LTTV_IRQ_UNKNOWN
);
2163 g_array_set_size(irqst
->mode_stack
, irqst
->mode_stack
->len
- 1);
2166 static void push_state(LttvTracefileState
*tfs
, LttvExecutionMode t
,
2169 LttvExecutionState
*es
;
2171 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
2172 guint cpu
= tfs
->cpu
;
2174 #ifdef HASH_TABLE_DEBUG
2175 hash_table_check(ts
->processes
);
2177 LttvProcessState
*process
= ts
->running_process
[cpu
];
2179 guint depth
= process
->execution_stack
->len
;
2181 process
->execution_stack
=
2182 g_array_set_size(process
->execution_stack
, depth
+ 1);
2185 &g_array_index(process
->execution_stack
, LttvExecutionState
, depth
- 1);
2187 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, depth
);
2190 es
->entry
= es
->change
= tfs
->parent
.timestamp
;
2191 es
->cum_cpu_time
= ltt_time_zero
;
2192 es
->s
= process
->state
->s
;
2193 process
->state
= es
;
2197 * return 1 when empty, else 0 */
2198 int lttv_state_pop_state_cleanup(LttvProcessState
*process
,
2199 LttvTracefileState
*tfs
)
2201 guint depth
= process
->execution_stack
->len
;
2207 process
->execution_stack
=
2208 g_array_set_size(process
->execution_stack
, depth
- 1);
2209 process
->state
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
2211 process
->state
->change
= tfs
->parent
.timestamp
;
2216 static void pop_state(LttvTracefileState
*tfs
, LttvExecutionMode t
)
2218 guint cpu
= tfs
->cpu
;
2219 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
2220 LttvProcessState
*process
= ts
->running_process
[cpu
];
2222 guint depth
= process
->execution_stack
->len
;
2224 if(process
->state
->t
!= t
){
2225 g_info("Different execution mode type (%lu.%09lu): ignore it\n",
2226 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
2227 g_info("process state has %s when pop_int is %s\n",
2228 g_quark_to_string(process
->state
->t
),
2229 g_quark_to_string(t
));
2230 g_info("{ %u, %u, %s, %s, %s }\n",
2233 g_quark_to_string(process
->name
),
2234 g_quark_to_string(process
->brand
),
2235 g_quark_to_string(process
->state
->s
));
2240 g_info("Trying to pop last state on stack (%lu.%09lu): ignore it\n",
2241 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
2245 process
->execution_stack
=
2246 g_array_set_size(process
->execution_stack
, depth
- 1);
2247 process
->state
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
2249 process
->state
->change
= tfs
->parent
.timestamp
;
2252 struct search_result
{
2253 const LttTime
*time
; /* Requested time */
2254 LttTime
*best
; /* Best result */
2257 static gint
search_usertrace(gconstpointer a
, gconstpointer b
)
2259 const LttTime
*elem_time
= (const LttTime
*)a
;
2260 /* Explicit non const cast */
2261 struct search_result
*res
= (struct search_result
*)b
;
2263 if(ltt_time_compare(*elem_time
, *(res
->time
)) < 0) {
2264 /* The usertrace was created before the schedchange */
2265 /* Get larger keys */
2267 } else if(ltt_time_compare(*elem_time
, *(res
->time
)) >= 0) {
2268 /* The usertrace was created after the schedchange time */
2269 /* Get smaller keys */
2271 if(ltt_time_compare(*elem_time
, *res
->best
) < 0) {
2272 res
->best
= (LttTime
*)elem_time
;
2275 res
->best
= (LttTime
*)elem_time
;
2282 static LttvTracefileState
*ltt_state_usertrace_find(LttvTraceState
*tcs
,
2283 guint pid
, const LttTime
*timestamp
)
2285 LttvTracefileState
*tfs
= NULL
;
2286 struct search_result res
;
2287 /* Find the usertrace associated with a pid and time interval.
2288 * Search in the usertraces by PID (within a hash) and then, for each
2289 * corresponding element of the array, find the first one with creation
2290 * timestamp the lowest, but higher or equal to "timestamp". */
2291 res
.time
= timestamp
;
2293 GTree
*usertrace_tree
= g_hash_table_lookup(tcs
->usertraces
,
2294 GUINT_TO_POINTER(pid
));
2295 if(usertrace_tree
) {
2296 g_tree_search(usertrace_tree
, search_usertrace
, &res
);
2298 tfs
= g_tree_lookup(usertrace_tree
, res
.best
);
2306 lttv_state_create_process(LttvTraceState
*tcs
, LttvProcessState
*parent
,
2307 guint cpu
, guint pid
, guint tgid
, GQuark name
, const LttTime
*timestamp
)
2309 LttvProcessState
*process
= g_new(LttvProcessState
, 1);
2311 LttvExecutionState
*es
;
2316 process
->tgid
= tgid
;
2318 process
->name
= name
;
2319 process
->brand
= LTTV_STATE_UNBRANDED
;
2320 //process->last_cpu = tfs->cpu_name;
2321 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
2322 process
->type
= LTTV_STATE_USER_THREAD
;
2323 process
->usertrace
= ltt_state_usertrace_find(tcs
, pid
, timestamp
);
2324 process
->current_function
= 0; //function 0x0 by default.
2326 g_info("Process %u, core %p", process
->pid
, process
);
2327 g_hash_table_insert(tcs
->processes
, process
, process
);
2330 process
->ppid
= parent
->pid
;
2331 process
->creation_time
= *timestamp
;
2334 /* No parent. This process exists but we are missing all information about
2335 its creation. The birth time is set to zero but we remember the time of
2340 process
->creation_time
= ltt_time_zero
;
2343 process
->insertion_time
= *timestamp
;
2344 sprintf(buffer
,"%d-%lu.%lu",pid
, process
->creation_time
.tv_sec
,
2345 process
->creation_time
.tv_nsec
);
2346 process
->pid_time
= g_quark_from_string(buffer
);
2348 process
->free_events
= 0;
2349 //process->last_cpu = tfs->cpu_name;
2350 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
2351 process
->execution_stack
= g_array_sized_new(FALSE
, FALSE
,
2352 sizeof(LttvExecutionState
), PREALLOCATED_EXECUTION_STACK
);
2353 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 2);
2354 es
= process
->state
= &g_array_index(process
->execution_stack
,
2355 LttvExecutionState
, 0);
2356 es
->t
= LTTV_STATE_USER_MODE
;
2357 es
->n
= LTTV_STATE_SUBMODE_NONE
;
2358 es
->entry
= *timestamp
;
2359 //g_assert(timestamp->tv_sec != 0);
2360 es
->change
= *timestamp
;
2361 es
->cum_cpu_time
= ltt_time_zero
;
2362 es
->s
= LTTV_STATE_RUN
;
2364 es
= process
->state
= &g_array_index(process
->execution_stack
,
2365 LttvExecutionState
, 1);
2366 es
->t
= LTTV_STATE_SYSCALL
;
2367 es
->n
= LTTV_STATE_SUBMODE_NONE
;
2368 es
->entry
= *timestamp
;
2369 //g_assert(timestamp->tv_sec != 0);
2370 es
->change
= *timestamp
;
2371 es
->cum_cpu_time
= ltt_time_zero
;
2372 es
->s
= LTTV_STATE_WAIT_FORK
;
2374 /* Allocate an empty function call stack. If it's empty, use 0x0. */
2375 process
->user_stack
= g_array_sized_new(FALSE
, FALSE
,
2376 sizeof(guint64
), 0);
2381 LttvProcessState
*lttv_state_find_process(LttvTraceState
*ts
, guint cpu
,
2384 LttvProcessState key
;
2385 LttvProcessState
*process
;
2389 process
= g_hash_table_lookup(ts
->processes
, &key
);
2394 lttv_state_find_process_or_create(LttvTraceState
*ts
, guint cpu
, guint pid
,
2395 const LttTime
*timestamp
)
2397 LttvProcessState
*process
= lttv_state_find_process(ts
, cpu
, pid
);
2398 LttvExecutionState
*es
;
2400 /* Put ltt_time_zero creation time for unexisting processes */
2401 if(unlikely(process
== NULL
)) {
2402 process
= lttv_state_create_process(ts
,
2403 NULL
, cpu
, pid
, 0, LTTV_STATE_UNNAMED
, timestamp
);
2404 /* We are not sure is it's a kernel thread or normal thread, put the
2405 * bottom stack state to unknown */
2406 process
->execution_stack
=
2407 g_array_set_size(process
->execution_stack
, 1);
2408 process
->state
= es
=
2409 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
2410 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
2411 es
->s
= LTTV_STATE_UNNAMED
;
2416 /* FIXME : this function should be called when we receive an event telling that
2417 * release_task has been called in the kernel. In happens generally when
2418 * the parent waits for its child terminaison, but may also happen in special
2419 * cases in the child's exit : when the parent ignores its children SIGCCHLD or
2420 * has the flag SA_NOCLDWAIT. It can also happen when the child is part
2421 * of a killed thread group, but isn't the leader.
2423 static int exit_process(LttvTracefileState
*tfs
, LttvProcessState
*process
)
2425 LttvTraceState
*ts
= LTTV_TRACE_STATE(tfs
->parent
.t_context
);
2426 LttvProcessState key
;
2428 /* Wait for both schedule with exit dead and process free to happen.
2429 * They can happen in any order. */
2430 if (++(process
->free_events
) < 2)
2433 key
.pid
= process
->pid
;
2434 key
.cpu
= process
->cpu
;
2435 g_hash_table_remove(ts
->processes
, &key
);
2436 g_array_free(process
->execution_stack
, TRUE
);
2437 g_array_free(process
->user_stack
, TRUE
);
2443 static void free_process_state(gpointer key
, gpointer value
,gpointer user_data
)
2445 g_array_free(((LttvProcessState
*)value
)->execution_stack
, TRUE
);
2446 g_array_free(((LttvProcessState
*)value
)->user_stack
, TRUE
);
2451 static void lttv_state_free_process_table(GHashTable
*processes
)
2453 g_hash_table_foreach(processes
, free_process_state
, NULL
);
2454 g_hash_table_destroy(processes
);
2458 static gboolean
syscall_entry(void *hook_data
, void *call_data
)
2460 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2462 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2463 LttvProcessState
*process
= ts
->running_process
[cpu
];
2464 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2465 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2466 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2467 LttvExecutionSubmode submode
;
2469 guint syscall
= ltt_event_get_unsigned(e
, f
);
2470 expand_syscall_table(ts
, syscall
);
2471 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->syscall_names
[syscall
];
2472 /* There can be no system call from PID 0 : unknown state */
2473 if(process
->pid
!= 0)
2474 push_state(s
, LTTV_STATE_SYSCALL
, submode
);
2479 static gboolean
syscall_exit(void *hook_data
, void *call_data
)
2481 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2483 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2484 LttvProcessState
*process
= ts
->running_process
[cpu
];
2486 /* There can be no system call from PID 0 : unknown state */
2487 if(process
->pid
!= 0)
2488 pop_state(s
, LTTV_STATE_SYSCALL
);
2493 static gboolean
trap_entry(void *hook_data
, void *call_data
)
2495 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2496 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2497 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2498 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2499 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2501 LttvExecutionSubmode submode
;
2503 guint64 trap
= ltt_event_get_long_unsigned(e
, f
);
2505 expand_trap_table(ts
, trap
);
2507 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->trap_names
[trap
];
2509 push_state(s
, LTTV_STATE_TRAP
, submode
);
2511 /* update cpu status */
2512 cpu_push_mode(s
->cpu_state
, LTTV_CPU_TRAP
);
2514 /* update trap status */
2515 s
->cpu_state
->last_trap
= trap
;
2516 ts
->trap_states
[trap
].running
++;
2521 static gboolean
trap_exit(void *hook_data
, void *call_data
)
2523 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2524 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2525 gint trap
= s
->cpu_state
->last_trap
;
2527 pop_state(s
, LTTV_STATE_TRAP
);
2529 /* update cpu status */
2530 cpu_pop_mode(s
->cpu_state
);
2532 /* update trap status */
2534 if(ts
->trap_states
[trap
].running
)
2535 ts
->trap_states
[trap
].running
--;
2540 static gboolean
irq_entry(void *hook_data
, void *call_data
)
2542 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2543 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2544 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2545 //guint8 ev_id = ltt_event_eventtype_id(e);
2546 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2547 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2549 LttvExecutionSubmode submode
;
2550 guint64 irq
= ltt_event_get_long_unsigned(e
, f
);
2552 expand_irq_table(ts
, irq
);
2554 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->irq_names
[irq
];
2556 /* Do something with the info about being in user or system mode when int? */
2557 push_state(s
, LTTV_STATE_IRQ
, submode
);
2559 /* update cpu status */
2560 cpu_push_mode(s
->cpu_state
, LTTV_CPU_IRQ
);
2562 /* update irq status */
2563 s
->cpu_state
->last_irq
= irq
;
2564 irq_push_mode(&ts
->irq_states
[irq
], LTTV_IRQ_BUSY
);
2569 static gboolean
soft_irq_exit(void *hook_data
, void *call_data
)
2571 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2572 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2573 gint softirq
= s
->cpu_state
->last_soft_irq
;
2575 pop_state(s
, LTTV_STATE_SOFT_IRQ
);
2577 /* update softirq status */
2579 if(ts
->soft_irq_states
[softirq
].running
)
2580 ts
->soft_irq_states
[softirq
].running
--;
2582 /* update cpu status */
2583 cpu_pop_mode(s
->cpu_state
);
2588 static gboolean
irq_exit(void *hook_data
, void *call_data
)
2590 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2591 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2593 pop_state(s
, LTTV_STATE_IRQ
);
2595 /* update cpu status */
2596 cpu_pop_mode(s
->cpu_state
);
2598 /* update irq status */
2599 if (s
->cpu_state
->last_irq
!= -1)
2600 irq_pop_mode(&ts
->irq_states
[s
->cpu_state
->last_irq
]);
2605 static gboolean
soft_irq_raise(void *hook_data
, void *call_data
)
2607 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2608 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2609 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2610 //guint8 ev_id = ltt_event_eventtype_id(e);
2611 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2612 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2614 LttvExecutionSubmode submode
;
2615 guint64 softirq
= ltt_event_get_long_unsigned(e
, f
);
2616 guint64 nb_softirqs
= ((LttvTraceState
*)(s
->parent
.t_context
))->nb_soft_irqs
;
2618 if(softirq
< nb_softirqs
) {
2619 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->soft_irq_names
[softirq
];
2621 /* Fixup an incomplete irq table */
2622 GString
*string
= g_string_new("");
2623 g_string_printf(string
, "softirq %" PRIu64
, softirq
);
2624 submode
= g_quark_from_string(string
->str
);
2625 g_string_free(string
, TRUE
);
2628 /* update softirq status */
2629 /* a soft irq raises are not cumulative */
2630 ts
->soft_irq_states
[softirq
].pending
=1;
2635 static gboolean
soft_irq_entry(void *hook_data
, void *call_data
)
2637 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2638 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2639 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2640 //guint8 ev_id = ltt_event_eventtype_id(e);
2641 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2642 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2643 LttvExecutionSubmode submode
;
2644 guint64 softirq
= ltt_event_get_long_unsigned(e
, f
);
2645 expand_soft_irq_table(ts
, softirq
);
2646 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->soft_irq_names
[softirq
];
2648 /* Do something with the info about being in user or system mode when int? */
2649 push_state(s
, LTTV_STATE_SOFT_IRQ
, submode
);
2651 /* update cpu status */
2652 cpu_push_mode(s
->cpu_state
, LTTV_CPU_SOFT_IRQ
);
2654 /* update softirq status */
2655 s
->cpu_state
->last_soft_irq
= softirq
;
2656 if(ts
->soft_irq_states
[softirq
].pending
)
2657 ts
->soft_irq_states
[softirq
].pending
--;
2658 ts
->soft_irq_states
[softirq
].running
++;
2663 static gboolean
enum_interrupt(void *hook_data
, void *call_data
)
2665 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2666 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2667 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2668 //guint8 ev_id = ltt_event_eventtype_id(e);
2669 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2671 GQuark action
= g_quark_from_string(ltt_event_get_string(e
,
2672 lttv_trace_get_hook_field(th
, 0)));
2673 guint irq
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
2675 expand_irq_table(ts
, irq
);
2676 ts
->irq_names
[irq
] = action
;
2682 static gboolean
bdev_request_issue(void *hook_data
, void *call_data
)
2684 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2685 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2686 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2687 //guint8 ev_id = ltt_event_eventtype_id(e);
2688 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2690 guint major
= ltt_event_get_long_unsigned(e
,
2691 lttv_trace_get_hook_field(th
, 0));
2692 guint minor
= ltt_event_get_long_unsigned(e
,
2693 lttv_trace_get_hook_field(th
, 1));
2694 guint oper
= ltt_event_get_long_unsigned(e
,
2695 lttv_trace_get_hook_field(th
, 2));
2696 guint16 devcode
= MKDEV(major
,minor
);
2698 /* have we seen this block device before? */
2699 gpointer bdev
= get_hashed_bdevstate(ts
, devcode
);
2702 bdev_push_mode(bdev
, LTTV_BDEV_BUSY_READING
);
2704 bdev_push_mode(bdev
, LTTV_BDEV_BUSY_WRITING
);
2709 static gboolean
bdev_request_complete(void *hook_data
, void *call_data
)
2711 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2712 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2713 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2714 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2716 guint major
= ltt_event_get_long_unsigned(e
,
2717 lttv_trace_get_hook_field(th
, 0));
2718 guint minor
= ltt_event_get_long_unsigned(e
,
2719 lttv_trace_get_hook_field(th
, 1));
2720 //guint oper = ltt_event_get_long_unsigned(e,
2721 // lttv_trace_get_hook_field(th, 2));
2722 guint16 devcode
= MKDEV(major
,minor
);
2724 /* have we seen this block device before? */
2725 gpointer bdev
= get_hashed_bdevstate(ts
, devcode
);
2727 /* update block device */
2728 bdev_pop_mode(bdev
);
2733 static void push_function(LttvTracefileState
*tfs
, guint64 funcptr
)
2737 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
2738 guint cpu
= tfs
->cpu
;
2739 LttvProcessState
*process
= ts
->running_process
[cpu
];
2741 guint depth
= process
->user_stack
->len
;
2743 process
->user_stack
=
2744 g_array_set_size(process
->user_stack
, depth
+ 1);
2746 new_func
= &g_array_index(process
->user_stack
, guint64
, depth
);
2747 *new_func
= funcptr
;
2748 process
->current_function
= funcptr
;
2751 static void pop_function(LttvTracefileState
*tfs
, guint64 funcptr
)
2753 guint cpu
= tfs
->cpu
;
2754 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
2755 LttvProcessState
*process
= ts
->running_process
[cpu
];
2757 if(process
->current_function
!= funcptr
){
2758 g_info("Different functions (%lu.%09lu): ignore it\n",
2759 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
2760 g_info("process state has %" PRIu64
" when pop_function is %" PRIu64
"\n",
2761 process
->current_function
, funcptr
);
2762 g_info("{ %u, %u, %s, %s, %s }\n",
2765 g_quark_to_string(process
->name
),
2766 g_quark_to_string(process
->brand
),
2767 g_quark_to_string(process
->state
->s
));
2770 guint depth
= process
->user_stack
->len
;
2773 g_info("Trying to pop last function on stack (%lu.%09lu): ignore it\n",
2774 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
2778 process
->user_stack
=
2779 g_array_set_size(process
->user_stack
, depth
- 1);
2780 process
->current_function
=
2781 g_array_index(process
->user_stack
, guint64
, depth
- 2);
2785 static gboolean
function_entry(void *hook_data
, void *call_data
)
2787 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2788 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2789 //guint8 ev_id = ltt_event_eventtype_id(e);
2790 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2791 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2792 guint64 funcptr
= ltt_event_get_long_unsigned(e
, f
);
2794 push_function(s
, funcptr
);
2798 static gboolean
function_exit(void *hook_data
, void *call_data
)
2800 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2801 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2802 //guint8 ev_id = ltt_event_eventtype_id(e);
2803 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2804 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2805 guint64 funcptr
= ltt_event_get_long_unsigned(e
, f
);
2807 pop_function(s
, funcptr
);
2811 static gboolean
dump_syscall(void *hook_data
, void *call_data
)
2813 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2814 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2815 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2816 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2821 id
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2822 address
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
2823 symbol
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 2));
2825 expand_syscall_table(ts
, id
);
2826 ts
->syscall_names
[id
] = g_quark_from_string(symbol
);
2831 static gboolean
dump_kprobe(void *hook_data
, void *call_data
)
2833 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2834 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2835 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2836 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2840 ip
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2841 symbol
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 1));
2843 expand_kprobe_table(ts
, ip
, symbol
);
2848 static gboolean
dump_softirq(void *hook_data
, void *call_data
)
2850 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2851 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2852 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2853 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2858 id
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2859 address
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
2860 symbol
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 2));
2862 expand_soft_irq_table(ts
, id
);
2863 ts
->soft_irq_names
[id
] = g_quark_from_string(symbol
);
2868 static gboolean
schedchange(void *hook_data
, void *call_data
)
2870 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2872 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2873 LttvProcessState
*process
= ts
->running_process
[cpu
];
2874 //LttvProcessState *old_process = ts->running_process[cpu];
2876 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2877 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2878 guint pid_in
, pid_out
;
2881 pid_out
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2882 pid_in
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
2883 state_out
= ltt_event_get_long_int(e
, lttv_trace_get_hook_field(th
, 2));
2885 if(likely(process
!= NULL
)) {
2887 /* We could not know but it was not the idle process executing.
2888 This should only happen at the beginning, before the first schedule
2889 event, and when the initial information (current process for each CPU)
2890 is missing. It is not obvious how we could, after the fact, compensate
2891 the wrongly attributed statistics. */
2893 //This test only makes sense once the state is known and if there is no
2894 //missing events. We need to silently ignore schedchange coming after a
2895 //process_free, or it causes glitches. (FIXME)
2896 //if(unlikely(process->pid != pid_out)) {
2897 // g_assert(process->pid == 0);
2899 if(process
->pid
== 0
2900 && process
->state
->t
== LTTV_STATE_MODE_UNKNOWN
) {
2902 /* Scheduling out of pid 0 at beginning of the trace :
2903 * we know for sure it is in syscall mode at this point. */
2904 g_assert(process
->execution_stack
->len
== 1);
2905 process
->state
->t
= LTTV_STATE_SYSCALL
;
2906 process
->state
->s
= LTTV_STATE_WAIT
;
2907 process
->state
->change
= s
->parent
.timestamp
;
2908 process
->state
->entry
= s
->parent
.timestamp
;
2911 if(unlikely(process
->state
->s
== LTTV_STATE_EXIT
)) {
2912 process
->state
->s
= LTTV_STATE_ZOMBIE
;
2913 process
->state
->change
= s
->parent
.timestamp
;
2915 if(unlikely(state_out
== 0)) process
->state
->s
= LTTV_STATE_WAIT_CPU
;
2916 else process
->state
->s
= LTTV_STATE_WAIT
;
2917 process
->state
->change
= s
->parent
.timestamp
;
2920 if(state_out
== 32 || state_out
== 64) { /* EXIT_DEAD || TASK_DEAD */
2921 /* see sched.h for states */
2922 if (!exit_process(s
, process
)) {
2923 process
->state
->s
= LTTV_STATE_DEAD
;
2924 process
->state
->change
= s
->parent
.timestamp
;
2929 process
= ts
->running_process
[cpu
] =
2930 lttv_state_find_process_or_create(
2931 (LttvTraceState
*)s
->parent
.t_context
,
2933 &s
->parent
.timestamp
);
2934 process
->state
->s
= LTTV_STATE_RUN
;
2936 if(process
->usertrace
)
2937 process
->usertrace
->cpu
= cpu
;
2938 // process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)s)->tf);
2939 process
->state
->change
= s
->parent
.timestamp
;
2941 /* update cpu status */
2943 /* going to idle task */
2944 cpu_set_base_mode(s
->cpu_state
, LTTV_CPU_IDLE
);
2946 /* scheduling a real task.
2947 * we must be careful here:
2948 * if we just schedule()'ed to a process that is
2949 * in a trap, we must put the cpu in trap mode
2951 cpu_set_base_mode(s
->cpu_state
, LTTV_CPU_BUSY
);
2952 if(process
->state
->t
== LTTV_STATE_TRAP
)
2953 cpu_push_mode(s
->cpu_state
, LTTV_CPU_TRAP
);
2959 static gboolean
process_fork(void *hook_data
, void *call_data
)
2961 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2962 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2963 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2965 guint child_pid
; /* In the Linux Kernel, there is one PID per thread. */
2966 guint child_tgid
; /* tgid in the Linux kernel is the "real" POSIX PID. */
2967 //LttvProcessState *zombie_process;
2969 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2970 LttvProcessState
*process
= ts
->running_process
[cpu
];
2971 LttvProcessState
*child_process
;
2972 struct marker_field
*f
;
2975 parent_pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2978 child_pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
2979 s
->parent
.target_pid
= child_pid
;
2982 f
= lttv_trace_get_hook_field(th
, 2);
2984 child_tgid
= ltt_event_get_unsigned(e
, f
);
2988 /* Mathieu : it seems like the process might have been scheduled in before the
2989 * fork, and, in a rare case, might be the current process. This might happen
2990 * in a SMP case where we don't have enough precision on the clocks.
2992 * Test reenabled after precision fixes on time. (Mathieu) */
2994 zombie_process
= lttv_state_find_process(ts
, ANY_CPU
, child_pid
);
2996 if(unlikely(zombie_process
!= NULL
)) {
2997 /* Reutilisation of PID. Only now we are sure that the old PID
2998 * has been released. FIXME : should know when release_task happens instead.
3000 guint num_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
3002 for(i
=0; i
< num_cpus
; i
++) {
3003 g_assert(zombie_process
!= ts
->running_process
[i
]);
3006 exit_process(s
, zombie_process
);
3009 g_assert(process
->pid
!= child_pid
);
3010 // FIXME : Add this test in the "known state" section
3011 // g_assert(process->pid == parent_pid);
3012 child_process
= lttv_state_find_process(ts
, ANY_CPU
, child_pid
);
3013 if(child_process
== NULL
) {
3014 child_process
= lttv_state_create_process(ts
, process
, cpu
,
3015 child_pid
, child_tgid
,
3016 LTTV_STATE_UNNAMED
, &s
->parent
.timestamp
);
3018 /* The process has already been created : due to time imprecision between
3019 * multiple CPUs : it has been scheduled in before creation. Note that we
3020 * shouldn't have this kind of imprecision.
3022 * Simply put a correct parent.
3024 g_error("Process %u has been created at [%lu.%09lu] "
3025 "and inserted at [%lu.%09lu] before \n"
3026 "fork on cpu %u[%lu.%09lu].\n"
3027 "Probably an unsynchronized TSC problem on the traced machine.",
3029 child_process
->creation_time
.tv_sec
,
3030 child_process
->creation_time
.tv_nsec
,
3031 child_process
->insertion_time
.tv_sec
,
3032 child_process
->insertion_time
.tv_nsec
,
3033 cpu
, ltt_event_time(e
).tv_sec
, ltt_event_time(e
).tv_nsec
);
3034 //g_assert(0); /* This is a problematic case : the process has been created
3035 // before the fork event */
3036 child_process
->ppid
= process
->pid
;
3037 child_process
->tgid
= child_tgid
;
3039 g_assert(child_process
->name
== LTTV_STATE_UNNAMED
);
3040 child_process
->name
= process
->name
;
3041 child_process
->brand
= process
->brand
;
3046 /* We stamp a newly created process as kernel_thread.
3047 * The thread should not be running yet. */
3048 static gboolean
process_kernel_thread(void *hook_data
, void *call_data
)
3050 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3051 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3052 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3054 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3055 LttvProcessState
*process
;
3056 LttvExecutionState
*es
;
3059 pid
= (guint
)ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
3060 s
->parent
.target_pid
= pid
;
3062 process
= lttv_state_find_process_or_create(ts
, ANY_CPU
, pid
,
3064 if (process
->state
->s
!= LTTV_STATE_DEAD
) {
3065 process
->execution_stack
=
3066 g_array_set_size(process
->execution_stack
, 1);
3067 es
= process
->state
=
3068 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3069 es
->t
= LTTV_STATE_SYSCALL
;
3071 process
->type
= LTTV_STATE_KERNEL_THREAD
;
3076 static gboolean
process_exit(void *hook_data
, void *call_data
)
3078 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3079 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3080 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3082 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3083 LttvProcessState
*process
; // = ts->running_process[cpu];
3085 pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
3086 s
->parent
.target_pid
= pid
;
3088 // FIXME : Add this test in the "known state" section
3089 // g_assert(process->pid == pid);
3091 process
= lttv_state_find_process(ts
, ANY_CPU
, pid
);
3092 if(likely(process
!= NULL
)) {
3093 process
->state
->s
= LTTV_STATE_EXIT
;
3098 static gboolean
process_free(void *hook_data
, void *call_data
)
3100 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3101 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3102 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3103 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3105 LttvProcessState
*process
;
3107 /* PID of the process to release */
3108 release_pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
3109 s
->parent
.target_pid
= release_pid
;
3111 g_assert(release_pid
!= 0);
3113 process
= lttv_state_find_process(ts
, ANY_CPU
, release_pid
);
3114 if(likely(process
!= NULL
))
3115 exit_process(s
, process
);
3118 if(likely(process
!= NULL
)) {
3119 /* release_task is happening at kernel level : we can now safely release
3120 * the data structure of the process */
3121 //This test is fun, though, as it may happen that
3122 //at time t : CPU 0 : process_free
3123 //at time t+150ns : CPU 1 : schedule out
3124 //Clearly due to time imprecision, we disable it. (Mathieu)
3125 //If this weird case happen, we have no choice but to put the
3126 //Currently running process on the cpu to 0.
3127 //I re-enable it following time precision fixes. (Mathieu)
3128 //Well, in the case where an process is freed by a process on another CPU
3129 //and still scheduled, it happens that this is the schedchange that will
3130 //drop the last reference count. Do not free it here!
3131 guint num_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
3133 for(i
=0; i
< num_cpus
; i
++) {
3134 //g_assert(process != ts->running_process[i]);
3135 if(process
== ts
->running_process
[i
]) {
3136 //ts->running_process[i] = lttv_state_find_process(ts, i, 0);
3140 if(i
== num_cpus
) /* process is not scheduled */
3141 exit_process(s
, process
);
3148 static gboolean
process_exec(void *hook_data
, void *call_data
)
3150 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3151 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3152 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3153 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3156 LttvProcessState
*process
= ts
->running_process
[cpu
];
3158 #if 0//how to use a sequence that must be transformed in a string
3159 /* PID of the process to release */
3160 guint64 name_len
= ltt_event_field_element_number(e
,
3161 lttv_trace_get_hook_field(th
, 0));
3162 //name = ltt_event_get_string(e, lttv_trace_get_hook_field(th, 0));
3163 LttField
*child
= ltt_event_field_element_select(e
,
3164 lttv_trace_get_hook_field(th
, 0), 0);
3166 (gchar
*)(ltt_event_data(e
)+ltt_event_field_offset(e
, child
));
3167 gchar
*null_term_name
= g_new(gchar
, name_len
+1);
3168 memcpy(null_term_name
, name_begin
, name_len
);
3169 null_term_name
[name_len
] = '\0';
3170 process
->name
= g_quark_from_string(null_term_name
);
3173 process
->name
= g_quark_from_string(ltt_event_get_string(e
,
3174 lttv_trace_get_hook_field(th
, 0)));
3175 process
->brand
= LTTV_STATE_UNBRANDED
;
3176 //g_free(null_term_name);
3180 static gboolean
thread_brand(void *hook_data
, void *call_data
)
3182 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3183 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3184 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3185 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3188 LttvProcessState
*process
= ts
->running_process
[cpu
];
3190 name
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 0));
3191 process
->brand
= g_quark_from_string(name
);
3196 static void fix_process(gpointer key
, gpointer value
,
3199 LttvProcessState
*process
;
3200 LttvExecutionState
*es
;
3201 process
= (LttvProcessState
*)value
;
3202 LttTime
*timestamp
= (LttTime
*)user_data
;
3204 if(process
->type
== LTTV_STATE_KERNEL_THREAD
) {
3205 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3206 if(es
->t
== LTTV_STATE_MODE_UNKNOWN
) {
3207 es
->t
= LTTV_STATE_SYSCALL
;
3208 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3209 es
->entry
= *timestamp
;
3210 es
->change
= *timestamp
;
3211 es
->cum_cpu_time
= ltt_time_zero
;
3212 if(es
->s
== LTTV_STATE_UNNAMED
)
3213 es
->s
= LTTV_STATE_WAIT
;
3216 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3217 if(es
->t
== LTTV_STATE_MODE_UNKNOWN
) {
3218 es
->t
= LTTV_STATE_USER_MODE
;
3219 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3220 es
->entry
= *timestamp
;
3221 //g_assert(timestamp->tv_sec != 0);
3222 es
->change
= *timestamp
;
3223 es
->cum_cpu_time
= ltt_time_zero
;
3224 if(es
->s
== LTTV_STATE_UNNAMED
)
3225 es
->s
= LTTV_STATE_RUN
;
3227 if(process
->execution_stack
->len
== 1) {
3228 /* Still in bottom unknown mode, means never did a system call
3229 * May be either in user mode, syscall mode, running or waiting.*/
3230 /* FIXME : we may be tagging syscall mode when being user mode */
3231 process
->execution_stack
=
3232 g_array_set_size(process
->execution_stack
, 2);
3233 es
= process
->state
= &g_array_index(process
->execution_stack
,
3234 LttvExecutionState
, 1);
3235 es
->t
= LTTV_STATE_SYSCALL
;
3236 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3237 es
->entry
= *timestamp
;
3238 //g_assert(timestamp->tv_sec != 0);
3239 es
->change
= *timestamp
;
3240 es
->cum_cpu_time
= ltt_time_zero
;
3241 if(es
->s
== LTTV_STATE_WAIT_FORK
)
3242 es
->s
= LTTV_STATE_WAIT
;
3248 static gboolean
statedump_end(void *hook_data
, void *call_data
)
3250 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3251 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3252 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
3253 //LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
3254 //LttvTraceHook *th = (LttvTraceHook *)hook_data;
3256 /* For all processes */
3257 /* if kernel thread, if stack[0] is unknown, set to syscall mode, wait */
3258 /* else, if stack[0] is unknown, set to user mode, running */
3260 g_hash_table_foreach(ts
->processes
, fix_process
, &tfc
->timestamp
);
3265 static gboolean
enum_process_state(void *hook_data
, void *call_data
)
3267 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3268 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3269 //It's slow : optimise later by doing this before reading trace.
3270 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3276 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3277 LttvProcessState
*process
= ts
->running_process
[cpu
];
3278 LttvProcessState
*parent_process
;
3279 struct marker_field
*f
;
3280 GQuark type
, mode
, submode
, status
;
3281 LttvExecutionState
*es
;
3285 pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
3286 s
->parent
.target_pid
= pid
;
3289 parent_pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
3292 command
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 2));
3295 f
= lttv_trace_get_hook_field(th
, 3);
3296 type
= ltt_enum_string_get(f
, ltt_event_get_unsigned(e
, f
));
3298 //FIXME: type is rarely used, enum must match possible types.
3301 f
= lttv_trace_get_hook_field(th
, 4);
3302 mode
= ltt_enum_string_get(f
,ltt_event_get_unsigned(e
, f
));
3305 f
= lttv_trace_get_hook_field(th
, 5);
3306 submode
= ltt_enum_string_get(f
, ltt_event_get_unsigned(e
, f
));
3309 f
= lttv_trace_get_hook_field(th
, 6);
3310 status
= ltt_enum_string_get(f
, ltt_event_get_unsigned(e
, f
));
3313 f
= lttv_trace_get_hook_field(th
, 7);
3315 tgid
= ltt_event_get_unsigned(e
, f
);
3320 nb_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
3321 for(i
=0; i
<nb_cpus
; i
++) {
3322 process
= lttv_state_find_process(ts
, i
, pid
);
3323 g_assert(process
!= NULL
);
3325 process
->ppid
= parent_pid
;
3326 process
->tgid
= tgid
;
3327 process
->name
= g_quark_from_string(command
);
3329 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3330 process
->type
= LTTV_STATE_KERNEL_THREAD
;
3334 /* The process might exist if a process was forked while performing the
3336 process
= lttv_state_find_process(ts
, ANY_CPU
, pid
);
3337 if(process
== NULL
) {
3338 parent_process
= lttv_state_find_process(ts
, ANY_CPU
, parent_pid
);
3339 process
= lttv_state_create_process(ts
, parent_process
, cpu
,
3340 pid
, tgid
, g_quark_from_string(command
),
3341 &s
->parent
.timestamp
);
3343 /* Keep the stack bottom : a running user mode */
3344 /* Disabled because of inconsistencies in the current statedump states. */
3345 if(type
== LTTV_STATE_KERNEL_THREAD
) {
3346 /* Only keep the bottom
3347 * FIXME Kernel thread : can be in syscall or interrupt or trap. */
3348 /* Will cause expected trap when in fact being syscall (even after end of
3350 * Will cause expected interrupt when being syscall. (only before end of
3351 * statedump event) */
3352 // This will cause a "popping last state on stack, ignoring it."
3353 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 1);
3354 es
= process
->state
= &g_array_index(process
->execution_stack
,
3355 LttvExecutionState
, 0);
3356 process
->type
= LTTV_STATE_KERNEL_THREAD
;
3357 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
3358 es
->s
= LTTV_STATE_UNNAMED
;
3359 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3361 es
->t
= LTTV_STATE_SYSCALL
;
3366 /* User space process :
3367 * bottom : user mode
3368 * either currently running or scheduled out.
3369 * can be scheduled out because interrupted in (user mode or in syscall)
3370 * or because of an explicit call to the scheduler in syscall. Note that
3371 * the scheduler call comes after the irq_exit, so never in interrupt
3373 // temp workaround : set size to 1 : only have user mode bottom of stack.
3374 // will cause g_info message of expected syscall mode when in fact being
3375 // in user mode. Can also cause expected trap when in fact being user
3376 // mode in the event of a page fault reenabling interrupts in the handler.
3377 // Expected syscall and trap can also happen after the end of statedump
3378 // This will cause a "popping last state on stack, ignoring it."
3379 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 1);
3380 es
= process
->state
= &g_array_index(process
->execution_stack
,
3381 LttvExecutionState
, 0);
3382 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
3383 es
->s
= LTTV_STATE_UNNAMED
;
3384 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3386 es
->t
= LTTV_STATE_USER_MODE
;
3394 es
= process
->state
= &g_array_index(process
->execution_stack
,
3395 LttvExecutionState
, 1);
3396 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
3397 es
->s
= LTTV_STATE_UNNAMED
;
3398 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3402 /* The process has already been created :
3403 * Probably was forked while dumping the process state or
3404 * was simply scheduled in prior to get the state dump event.
3406 process
->ppid
= parent_pid
;
3407 process
->tgid
= tgid
;
3408 process
->name
= g_quark_from_string(command
);
3409 process
->type
= type
;
3411 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3413 if(es
->t
== LTTV_STATE_MODE_UNKNOWN
) {
3414 if(type
== LTTV_STATE_KERNEL_THREAD
)
3415 es
->t
= LTTV_STATE_SYSCALL
;
3417 es
->t
= LTTV_STATE_USER_MODE
;
3420 /* Don't mess around with the stack, it will eventually become
3421 * ok after the end of state dump. */
3428 gint
lttv_state_hook_add_event_hooks(void *hook_data
, void *call_data
)
3430 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
3432 lttv_state_add_event_hooks(tss
);
3437 void lttv_state_add_event_hooks(LttvTracesetState
*self
)
3439 LttvTraceset
*traceset
= self
->parent
.ts
;
3441 guint i
, j
, k
, nb_trace
, nb_tracefile
;
3445 LttvTracefileState
*tfs
;
3451 LttvAttributeValue val
;
3453 nb_trace
= lttv_traceset_number(traceset
);
3454 for(i
= 0 ; i
< nb_trace
; i
++) {
3455 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
3457 /* Find the eventtype id for the following events and register the
3458 associated by id hooks. */
3460 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 20);
3461 //hooks = g_array_set_size(hooks, 19); // Max possible number of hooks.
3464 lttv_trace_find_hook(ts
->parent
.t
,
3466 LTT_EVENT_SYSCALL_ENTRY
,
3467 FIELD_ARRAY(LTT_FIELD_SYSCALL_ID
),
3468 syscall_entry
, NULL
, &hooks
);
3470 lttv_trace_find_hook(ts
->parent
.t
,
3472 LTT_EVENT_SYSCALL_EXIT
,
3474 syscall_exit
, NULL
, &hooks
);
3476 lttv_trace_find_hook(ts
->parent
.t
,
3478 LTT_EVENT_TRAP_ENTRY
,
3479 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
3480 trap_entry
, NULL
, &hooks
);
3482 lttv_trace_find_hook(ts
->parent
.t
,
3484 LTT_EVENT_TRAP_EXIT
,
3486 trap_exit
, NULL
, &hooks
);
3488 lttv_trace_find_hook(ts
->parent
.t
,
3490 LTT_EVENT_PAGE_FAULT_ENTRY
,
3491 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
3492 trap_entry
, NULL
, &hooks
);
3494 lttv_trace_find_hook(ts
->parent
.t
,
3496 LTT_EVENT_PAGE_FAULT_EXIT
,
3498 trap_exit
, NULL
, &hooks
);
3500 lttv_trace_find_hook(ts
->parent
.t
,
3502 LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY
,
3503 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
3504 trap_entry
, NULL
, &hooks
);
3506 lttv_trace_find_hook(ts
->parent
.t
,
3508 LTT_EVENT_PAGE_FAULT_NOSEM_EXIT
,
3510 trap_exit
, NULL
, &hooks
);
3512 lttv_trace_find_hook(ts
->parent
.t
,
3514 LTT_EVENT_IRQ_ENTRY
,
3515 FIELD_ARRAY(LTT_FIELD_IRQ_ID
),
3516 irq_entry
, NULL
, &hooks
);
3518 lttv_trace_find_hook(ts
->parent
.t
,
3522 irq_exit
, NULL
, &hooks
);
3524 lttv_trace_find_hook(ts
->parent
.t
,
3526 LTT_EVENT_SOFT_IRQ_RAISE
,
3527 FIELD_ARRAY(LTT_FIELD_SOFT_IRQ_ID
),
3528 soft_irq_raise
, NULL
, &hooks
);
3530 lttv_trace_find_hook(ts
->parent
.t
,
3532 LTT_EVENT_SOFT_IRQ_ENTRY
,
3533 FIELD_ARRAY(LTT_FIELD_SOFT_IRQ_ID
),
3534 soft_irq_entry
, NULL
, &hooks
);
3536 lttv_trace_find_hook(ts
->parent
.t
,
3538 LTT_EVENT_SOFT_IRQ_EXIT
,
3540 soft_irq_exit
, NULL
, &hooks
);
3542 lttv_trace_find_hook(ts
->parent
.t
,
3544 LTT_EVENT_SCHED_SCHEDULE
,
3545 FIELD_ARRAY(LTT_FIELD_PREV_PID
, LTT_FIELD_NEXT_PID
,
3546 LTT_FIELD_PREV_STATE
),
3547 schedchange
, NULL
, &hooks
);
3549 lttv_trace_find_hook(ts
->parent
.t
,
3551 LTT_EVENT_PROCESS_FORK
,
3552 FIELD_ARRAY(LTT_FIELD_PARENT_PID
, LTT_FIELD_CHILD_PID
,
3553 LTT_FIELD_CHILD_TGID
),
3554 process_fork
, NULL
, &hooks
);
3556 lttv_trace_find_hook(ts
->parent
.t
,
3558 LTT_EVENT_KTHREAD_CREATE
,
3559 FIELD_ARRAY(LTT_FIELD_PID
),
3560 process_kernel_thread
, NULL
, &hooks
);
3562 lttv_trace_find_hook(ts
->parent
.t
,
3564 LTT_EVENT_PROCESS_EXIT
,
3565 FIELD_ARRAY(LTT_FIELD_PID
),
3566 process_exit
, NULL
, &hooks
);
3568 lttv_trace_find_hook(ts
->parent
.t
,
3570 LTT_EVENT_PROCESS_FREE
,
3571 FIELD_ARRAY(LTT_FIELD_PID
),
3572 process_free
, NULL
, &hooks
);
3574 lttv_trace_find_hook(ts
->parent
.t
,
3577 FIELD_ARRAY(LTT_FIELD_FILENAME
),
3578 process_exec
, NULL
, &hooks
);
3580 lttv_trace_find_hook(ts
->parent
.t
,
3581 LTT_CHANNEL_USERSPACE
,
3582 LTT_EVENT_THREAD_BRAND
,
3583 FIELD_ARRAY(LTT_FIELD_NAME
),
3584 thread_brand
, NULL
, &hooks
);
3586 /* statedump-related hooks */
3587 lttv_trace_find_hook(ts
->parent
.t
,
3588 LTT_CHANNEL_TASK_STATE
,
3589 LTT_EVENT_PROCESS_STATE
,
3590 FIELD_ARRAY(LTT_FIELD_PID
, LTT_FIELD_PARENT_PID
, LTT_FIELD_NAME
,
3591 LTT_FIELD_TYPE
, LTT_FIELD_MODE
, LTT_FIELD_SUBMODE
,
3592 LTT_FIELD_STATUS
, LTT_FIELD_TGID
),
3593 enum_process_state
, NULL
, &hooks
);
3595 lttv_trace_find_hook(ts
->parent
.t
,
3596 LTT_CHANNEL_GLOBAL_STATE
,
3597 LTT_EVENT_STATEDUMP_END
,
3599 statedump_end
, NULL
, &hooks
);
3601 lttv_trace_find_hook(ts
->parent
.t
,
3602 LTT_CHANNEL_IRQ_STATE
,
3603 LTT_EVENT_LIST_INTERRUPT
,
3604 FIELD_ARRAY(LTT_FIELD_ACTION
, LTT_FIELD_IRQ_ID
),
3605 enum_interrupt
, NULL
, &hooks
);
3607 lttv_trace_find_hook(ts
->parent
.t
,
3609 LTT_EVENT_REQUEST_ISSUE
,
3610 FIELD_ARRAY(LTT_FIELD_MAJOR
, LTT_FIELD_MINOR
, LTT_FIELD_OPERATION
),
3611 bdev_request_issue
, NULL
, &hooks
);
3613 lttv_trace_find_hook(ts
->parent
.t
,
3615 LTT_EVENT_REQUEST_COMPLETE
,
3616 FIELD_ARRAY(LTT_FIELD_MAJOR
, LTT_FIELD_MINOR
, LTT_FIELD_OPERATION
),
3617 bdev_request_complete
, NULL
, &hooks
);
3619 lttv_trace_find_hook(ts
->parent
.t
,
3620 LTT_CHANNEL_USERSPACE
,
3621 LTT_EVENT_FUNCTION_ENTRY
,
3622 FIELD_ARRAY(LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
),
3623 function_entry
, NULL
, &hooks
);
3625 lttv_trace_find_hook(ts
->parent
.t
,
3626 LTT_CHANNEL_USERSPACE
,
3627 LTT_EVENT_FUNCTION_EXIT
,
3628 FIELD_ARRAY(LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
),
3629 function_exit
, NULL
, &hooks
);
3631 lttv_trace_find_hook(ts
->parent
.t
,
3632 LTT_CHANNEL_SYSCALL_STATE
,
3633 LTT_EVENT_SYS_CALL_TABLE
,
3634 FIELD_ARRAY(LTT_FIELD_ID
, LTT_FIELD_ADDRESS
, LTT_FIELD_SYMBOL
),
3635 dump_syscall
, NULL
, &hooks
);
3637 lttv_trace_find_hook(ts
->parent
.t
,
3638 LTT_CHANNEL_KPROBE_STATE
,
3639 LTT_EVENT_KPROBE_TABLE
,
3640 FIELD_ARRAY(LTT_FIELD_IP
, LTT_FIELD_SYMBOL
),
3641 dump_kprobe
, NULL
, &hooks
);
3643 lttv_trace_find_hook(ts
->parent
.t
,
3644 LTT_CHANNEL_SOFTIRQ_STATE
,
3645 LTT_EVENT_SOFTIRQ_VEC
,
3646 FIELD_ARRAY(LTT_FIELD_ID
, LTT_FIELD_ADDRESS
, LTT_FIELD_SYMBOL
),
3647 dump_softirq
, NULL
, &hooks
);
3649 /* Add these hooks to each event_by_id hooks list */
3651 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3653 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3655 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
3656 LttvTracefileContext
*, j
));
3658 for(k
= 0 ; k
< hooks
->len
; k
++) {
3659 th
= &g_array_index(hooks
, LttvTraceHook
, k
);
3660 if (th
->mdata
== tfs
->parent
.tf
->mdata
)
3662 lttv_hooks_by_id_find(tfs
->parent
.event_by_id
, th
->id
),
3668 lttv_attribute_find(ts
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
3669 *(val
.v_pointer
) = hooks
;
3673 gint
lttv_state_hook_remove_event_hooks(void *hook_data
, void *call_data
)
3675 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
3677 lttv_state_remove_event_hooks(tss
);
3682 void lttv_state_remove_event_hooks(LttvTracesetState
*self
)
3684 LttvTraceset
*traceset
= self
->parent
.ts
;
3686 guint i
, j
, k
, nb_trace
, nb_tracefile
;
3690 LttvTracefileState
*tfs
;
3696 LttvAttributeValue val
;
3698 nb_trace
= lttv_traceset_number(traceset
);
3699 for(i
= 0 ; i
< nb_trace
; i
++) {
3700 ts
= LTTV_TRACE_STATE(self
->parent
.traces
[i
]);
3702 lttv_attribute_find(ts
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
3703 hooks
= *(val
.v_pointer
);
3705 /* Remove these hooks from each event_by_id hooks list */
3707 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3709 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3711 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
3712 LttvTracefileContext
*, j
));
3714 for(k
= 0 ; k
< hooks
->len
; k
++) {
3715 th
= &g_array_index(hooks
, LttvTraceHook
, k
);
3716 if (th
->mdata
== tfs
->parent
.tf
->mdata
)
3717 lttv_hooks_remove_data(
3718 lttv_hooks_by_id_find(tfs
->parent
.event_by_id
, th
->id
),
3723 lttv_trace_hook_remove_all(&hooks
);
3724 g_array_free(hooks
, TRUE
);
3728 static gboolean
state_save_event_hook(void *hook_data
, void *call_data
)
3730 guint
*event_count
= (guint
*)hook_data
;
3732 /* Only save at LTTV_STATE_SAVE_INTERVAL */
3733 if(likely((*event_count
)++ < LTTV_STATE_SAVE_INTERVAL
))
3738 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3740 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3742 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
3744 LttvAttributeValue value
;
3746 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
3747 LTTV_STATE_SAVED_STATES
);
3748 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
3749 value
= lttv_attribute_add(saved_states_tree
,
3750 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
3751 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
3752 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
3753 *(value
.v_time
) = self
->parent
.timestamp
;
3754 lttv_state_save(tcs
, saved_state_tree
);
3755 g_debug("Saving state at time %lu.%lu", self
->parent
.timestamp
.tv_sec
,
3756 self
->parent
.timestamp
.tv_nsec
);
3758 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
3763 static gboolean
state_save_after_trace_hook(void *hook_data
, void *call_data
)
3765 LttvTraceState
*tcs
= (LttvTraceState
*)(call_data
);
3767 *(tcs
->max_time_state_recomputed_in_seek
) = tcs
->parent
.time_span
.end_time
;
3772 guint
lttv_state_current_cpu(LttvTracefileState
*tfs
)
3780 static gboolean
block_start(void *hook_data
, void *call_data
)
3782 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3784 LttvTracefileState
*tfcs
;
3786 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3788 LttEventPosition
*ep
;
3790 guint i
, nb_block
, nb_event
, nb_tracefile
;
3794 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
3796 LttvAttributeValue value
;
3798 ep
= ltt_event_position_new();
3800 nb_tracefile
= tcs
->parent
.tracefiles
->len
;
3802 /* Count the number of events added since the last block end in any
3805 for(i
= 0 ; i
< nb_tracefile
; i
++) {
3807 LTTV_TRACEFILE_STATE(&g_array_index(tcs
->parent
.tracefiles
,
3808 LttvTracefileContext
, i
));
3809 ltt_event_position(tfcs
->parent
.e
, ep
);
3810 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
3811 tcs
->nb_event
+= nb_event
- tfcs
->saved_position
;
3812 tfcs
->saved_position
= nb_event
;
3816 if(tcs
->nb_event
>= tcs
->save_interval
) {
3817 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
3818 LTTV_STATE_SAVED_STATES
);
3819 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
3820 value
= lttv_attribute_add(saved_states_tree
,
3821 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
3822 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
3823 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
3824 *(value
.v_time
) = self
->parent
.timestamp
;
3825 lttv_state_save(tcs
, saved_state_tree
);
3827 g_debug("Saving state at time %lu.%lu", self
->parent
.timestamp
.tv_sec
,
3828 self
->parent
.timestamp
.tv_nsec
);
3830 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
3836 static gboolean
block_end(void *hook_data
, void *call_data
)
3838 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3840 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3844 LttEventPosition
*ep
;
3846 guint nb_block
, nb_event
;
3848 ep
= ltt_event_position_new();
3849 ltt_event_position(self
->parent
.e
, ep
);
3850 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
3851 tcs
->nb_event
+= nb_event
- self
->saved_position
+ 1;
3852 self
->saved_position
= 0;
3853 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
3860 void lttv_state_save_add_event_hooks(LttvTracesetState
*self
)
3862 LttvTraceset
*traceset
= self
->parent
.ts
;
3864 guint i
, j
, nb_trace
, nb_tracefile
;
3868 LttvTracefileState
*tfs
;
3870 LttvTraceHook hook_start
, hook_end
;
3872 nb_trace
= lttv_traceset_number(traceset
);
3873 for(i
= 0 ; i
< nb_trace
; i
++) {
3874 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
3876 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
3877 NULL
, NULL
, block_start
, &hook_start
);
3878 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
3879 NULL
, NULL
, block_end
, &hook_end
);
3881 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3883 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3885 LTTV_TRACEFILE_STATE(&g_array_index(ts
->parent
.tracefiles
,
3886 LttvTracefileContext
, j
));
3887 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
3888 hook_start
.id
), hook_start
.h
, NULL
, LTTV_PRIO_STATE
);
3889 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
3890 hook_end
.id
), hook_end
.h
, NULL
, LTTV_PRIO_STATE
);
3896 void lttv_state_save_add_event_hooks(LttvTracesetState
*self
)
3898 LttvTraceset
*traceset
= self
->parent
.ts
;
3900 guint i
, j
, nb_trace
, nb_tracefile
;
3904 LttvTracefileState
*tfs
;
3907 nb_trace
= lttv_traceset_number(traceset
);
3908 for(i
= 0 ; i
< nb_trace
; i
++) {
3910 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
3911 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3913 if(ts
->has_precomputed_states
) continue;
3915 guint
*event_count
= g_new(guint
, 1);
3918 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3920 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
3921 LttvTracefileContext
*, j
));
3922 lttv_hooks_add(tfs
->parent
.event
,
3923 state_save_event_hook
,
3930 lttv_process_traceset_begin(&self
->parent
,
3931 NULL
, NULL
, NULL
, NULL
, NULL
);
3935 gint
lttv_state_save_hook_add_event_hooks(void *hook_data
, void *call_data
)
3937 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
3939 lttv_state_save_add_event_hooks(tss
);
3946 void lttv_state_save_remove_event_hooks(LttvTracesetState
*self
)
3948 LttvTraceset
*traceset
= self
->parent
.ts
;
3950 guint i
, j
, nb_trace
, nb_tracefile
;
3954 LttvTracefileState
*tfs
;
3956 LttvTraceHook hook_start
, hook_end
;
3958 nb_trace
= lttv_traceset_number(traceset
);
3959 for(i
= 0 ; i
< nb_trace
; i
++) {
3960 ts
= LTTV_TRACE_STATE(self
->parent
.traces
[i
]);
3962 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
3963 NULL
, NULL
, block_start
, &hook_start
);
3965 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
3966 NULL
, NULL
, block_end
, &hook_end
);
3968 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3970 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3972 LTTV_TRACEFILE_STATE(&g_array_index(ts
->parent
.tracefiles
,
3973 LttvTracefileContext
, j
));
3974 lttv_hooks_remove_data(lttv_hooks_by_id_find(
3975 tfs
->parent
.event_by_id
, hook_start
.id
), hook_start
.h
, NULL
);
3976 lttv_hooks_remove_data(lttv_hooks_by_id_find(
3977 tfs
->parent
.event_by_id
, hook_end
.id
), hook_end
.h
, NULL
);
3983 void lttv_state_save_remove_event_hooks(LttvTracesetState
*self
)
3985 LttvTraceset
*traceset
= self
->parent
.ts
;
3987 guint i
, j
, nb_trace
, nb_tracefile
;
3991 LttvTracefileState
*tfs
;
3993 LttvHooks
*after_trace
= lttv_hooks_new();
3995 lttv_hooks_add(after_trace
,
3996 state_save_after_trace_hook
,
4001 lttv_process_traceset_end(&self
->parent
,
4002 NULL
, after_trace
, NULL
, NULL
, NULL
);
4004 lttv_hooks_destroy(after_trace
);
4006 nb_trace
= lttv_traceset_number(traceset
);
4007 for(i
= 0 ; i
< nb_trace
; i
++) {
4009 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
4010 nb_tracefile
= ts
->parent
.tracefiles
->len
;
4012 if(ts
->has_precomputed_states
) continue;
4014 guint
*event_count
= NULL
;
4016 for(j
= 0 ; j
< nb_tracefile
; j
++) {
4018 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
4019 LttvTracefileContext
*, j
));
4020 event_count
= lttv_hooks_remove(tfs
->parent
.event
,
4021 state_save_event_hook
);
4023 if(event_count
) g_free(event_count
);
4027 gint
lttv_state_save_hook_remove_event_hooks(void *hook_data
, void *call_data
)
4029 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
4031 lttv_state_save_remove_event_hooks(tss
);
4036 void lttv_state_traceset_seek_time_closest(LttvTracesetState
*self
, LttTime t
)
4038 LttvTraceset
*traceset
= self
->parent
.ts
;
4042 int min_pos
, mid_pos
, max_pos
;
4044 guint call_rest
= 0;
4046 LttvTraceState
*tcs
;
4048 LttvAttributeValue value
;
4050 LttvAttributeType type
;
4052 LttvAttributeName name
;
4056 LttvAttribute
*saved_states_tree
, *saved_state_tree
, *closest_tree
= NULL
;
4058 //g_tree_destroy(self->parent.pqueue);
4059 //self->parent.pqueue = g_tree_new(compare_tracefile);
4061 g_info("Entering seek_time_closest for time %lu.%lu", t
.tv_sec
, t
.tv_nsec
);
4063 nb_trace
= lttv_traceset_number(traceset
);
4064 for(i
= 0 ; i
< nb_trace
; i
++) {
4065 tcs
= (LttvTraceState
*)self
->parent
.traces
[i
];
4067 if(ltt_time_compare(t
, *(tcs
->max_time_state_recomputed_in_seek
)) < 0) {
4068 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
4069 LTTV_STATE_SAVED_STATES
);
4072 if(saved_states_tree
) {
4073 max_pos
= lttv_attribute_get_number(saved_states_tree
) - 1;
4074 mid_pos
= max_pos
/ 2;
4075 while(min_pos
< max_pos
) {
4076 type
= lttv_attribute_get(saved_states_tree
, mid_pos
, &name
, &value
,
4078 g_assert(type
== LTTV_GOBJECT
);
4079 saved_state_tree
= *((LttvAttribute
**)(value
.v_gobject
));
4080 type
= lttv_attribute_get_by_name(saved_state_tree
, LTTV_STATE_TIME
,
4082 g_assert(type
== LTTV_TIME
);
4083 if(ltt_time_compare(*(value
.v_time
), t
) < 0) {
4085 closest_tree
= saved_state_tree
;
4087 else max_pos
= mid_pos
- 1;
4089 mid_pos
= (min_pos
+ max_pos
+ 1) / 2;
4093 /* restore the closest earlier saved state */
4095 lttv_state_restore(tcs
, closest_tree
);
4099 /* There is no saved state, yet we want to have it. Restart at T0 */
4101 restore_init_state(tcs
);
4102 lttv_process_trace_seek_time(&(tcs
->parent
), ltt_time_zero
);
4105 /* We want to seek quickly without restoring/updating the state */
4107 restore_init_state(tcs
);
4108 lttv_process_trace_seek_time(&(tcs
->parent
), t
);
4111 if(!call_rest
) g_info("NOT Calling restore");
4116 traceset_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
4122 traceset_state_finalize (LttvTracesetState
*self
)
4124 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
4125 finalize(G_OBJECT(self
));
4130 traceset_state_class_init (LttvTracesetContextClass
*klass
)
4132 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
4134 gobject_class
->finalize
= (void (*)(GObject
*self
)) traceset_state_finalize
;
4135 klass
->init
= (void (*)(LttvTracesetContext
*self
, LttvTraceset
*ts
))init
;
4136 klass
->fini
= (void (*)(LttvTracesetContext
*self
))fini
;
4137 klass
->new_traceset_context
= new_traceset_context
;
4138 klass
->new_trace_context
= new_trace_context
;
4139 klass
->new_tracefile_context
= new_tracefile_context
;
4144 lttv_traceset_state_get_type(void)
4146 static GType type
= 0;
4148 static const GTypeInfo info
= {
4149 sizeof (LttvTracesetStateClass
),
4150 NULL
, /* base_init */
4151 NULL
, /* base_finalize */
4152 (GClassInitFunc
) traceset_state_class_init
, /* class_init */
4153 NULL
, /* class_finalize */
4154 NULL
, /* class_data */
4155 sizeof (LttvTracesetState
),
4156 0, /* n_preallocs */
4157 (GInstanceInitFunc
) traceset_state_instance_init
, /* instance_init */
4158 NULL
/* value handling */
4161 type
= g_type_register_static (LTTV_TRACESET_CONTEXT_TYPE
, "LttvTracesetStateType",
4169 trace_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
4175 trace_state_finalize (LttvTraceState
*self
)
4177 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_CONTEXT_TYPE
))->
4178 finalize(G_OBJECT(self
));
4183 trace_state_class_init (LttvTraceStateClass
*klass
)
4185 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
4187 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_state_finalize
;
4188 klass
->state_save
= state_save
;
4189 klass
->state_restore
= state_restore
;
4190 klass
->state_saved_free
= state_saved_free
;
4195 lttv_trace_state_get_type(void)
4197 static GType type
= 0;
4199 static const GTypeInfo info
= {
4200 sizeof (LttvTraceStateClass
),
4201 NULL
, /* base_init */
4202 NULL
, /* base_finalize */
4203 (GClassInitFunc
) trace_state_class_init
, /* class_init */
4204 NULL
, /* class_finalize */
4205 NULL
, /* class_data */
4206 sizeof (LttvTraceState
),
4207 0, /* n_preallocs */
4208 (GInstanceInitFunc
) trace_state_instance_init
, /* instance_init */
4209 NULL
/* value handling */
4212 type
= g_type_register_static (LTTV_TRACE_CONTEXT_TYPE
,
4213 "LttvTraceStateType", &info
, 0);
4220 tracefile_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
4226 tracefile_state_finalize (LttvTracefileState
*self
)
4228 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_CONTEXT_TYPE
))->
4229 finalize(G_OBJECT(self
));
4234 tracefile_state_class_init (LttvTracefileStateClass
*klass
)
4236 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
4238 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_state_finalize
;
4243 lttv_tracefile_state_get_type(void)
4245 static GType type
= 0;
4247 static const GTypeInfo info
= {
4248 sizeof (LttvTracefileStateClass
),
4249 NULL
, /* base_init */
4250 NULL
, /* base_finalize */
4251 (GClassInitFunc
) tracefile_state_class_init
, /* class_init */
4252 NULL
, /* class_finalize */
4253 NULL
, /* class_data */
4254 sizeof (LttvTracefileState
),
4255 0, /* n_preallocs */
4256 (GInstanceInitFunc
) tracefile_state_instance_init
, /* instance_init */
4257 NULL
/* value handling */
4260 type
= g_type_register_static (LTTV_TRACEFILE_CONTEXT_TYPE
,
4261 "LttvTracefileStateType", &info
, 0);
4267 static void module_init()
4269 LTTV_STATE_UNNAMED
= g_quark_from_string("");
4270 LTTV_STATE_UNBRANDED
= g_quark_from_string("");
4271 LTTV_STATE_MODE_UNKNOWN
= g_quark_from_string("MODE_UNKNOWN");
4272 LTTV_STATE_USER_MODE
= g_quark_from_string("USER_MODE");
4273 LTTV_STATE_SYSCALL
= g_quark_from_string("SYSCALL");
4274 LTTV_STATE_TRAP
= g_quark_from_string("TRAP");
4275 LTTV_STATE_IRQ
= g_quark_from_string("IRQ");
4276 LTTV_STATE_SOFT_IRQ
= g_quark_from_string("SOFTIRQ");
4277 LTTV_STATE_SUBMODE_UNKNOWN
= g_quark_from_string("UNKNOWN");
4278 LTTV_STATE_SUBMODE_NONE
= g_quark_from_string("NONE");
4279 LTTV_STATE_WAIT_FORK
= g_quark_from_string("WAIT_FORK");
4280 LTTV_STATE_WAIT_CPU
= g_quark_from_string("WAIT_CPU");
4281 LTTV_STATE_EXIT
= g_quark_from_string("EXIT");
4282 LTTV_STATE_ZOMBIE
= g_quark_from_string("ZOMBIE");
4283 LTTV_STATE_WAIT
= g_quark_from_string("WAIT");
4284 LTTV_STATE_RUN
= g_quark_from_string("RUN");
4285 LTTV_STATE_DEAD
= g_quark_from_string("DEAD");
4286 LTTV_STATE_USER_THREAD
= g_quark_from_string("USER_THREAD");
4287 LTTV_STATE_KERNEL_THREAD
= g_quark_from_string("KERNEL_THREAD");
4288 LTTV_STATE_TRACEFILES
= g_quark_from_string("tracefiles");
4289 LTTV_STATE_PROCESSES
= g_quark_from_string("processes");
4290 LTTV_STATE_PROCESS
= g_quark_from_string("process");
4291 LTTV_STATE_RUNNING_PROCESS
= g_quark_from_string("running_process");
4292 LTTV_STATE_EVENT
= g_quark_from_string("event");
4293 LTTV_STATE_SAVED_STATES
= g_quark_from_string("saved states");
4294 LTTV_STATE_SAVED_STATES_TIME
= g_quark_from_string("saved states time");
4295 LTTV_STATE_TIME
= g_quark_from_string("time");
4296 LTTV_STATE_HOOKS
= g_quark_from_string("saved state hooks");
4297 LTTV_STATE_NAME_TABLES
= g_quark_from_string("name tables");
4298 LTTV_STATE_TRACE_STATE_USE_COUNT
=
4299 g_quark_from_string("trace_state_use_count");
4300 LTTV_STATE_RESOURCE_CPUS
= g_quark_from_string("cpu resource states");
4301 LTTV_STATE_RESOURCE_CPUS
= g_quark_from_string("cpu count");
4302 LTTV_STATE_RESOURCE_IRQS
= g_quark_from_string("irq resource states");
4303 LTTV_STATE_RESOURCE_SOFT_IRQS
= g_quark_from_string("soft irq resource states");
4304 LTTV_STATE_RESOURCE_TRAPS
= g_quark_from_string("trap resource states");
4305 LTTV_STATE_RESOURCE_BLKDEVS
= g_quark_from_string("blkdevs resource states");
4307 LTT_CHANNEL_FD_STATE
= g_quark_from_string("fd_state");
4308 LTT_CHANNEL_GLOBAL_STATE
= g_quark_from_string("global_state");
4309 LTT_CHANNEL_IRQ_STATE
= g_quark_from_string("irq_state");
4310 LTT_CHANNEL_MODULE_STATE
= g_quark_from_string("module_state");
4311 LTT_CHANNEL_NETIF_STATE
= g_quark_from_string("netif_state");
4312 LTT_CHANNEL_SOFTIRQ_STATE
= g_quark_from_string("softirq_state");
4313 LTT_CHANNEL_SWAP_STATE
= g_quark_from_string("swap_state");
4314 LTT_CHANNEL_SYSCALL_STATE
= g_quark_from_string("syscall_state");
4315 LTT_CHANNEL_TASK_STATE
= g_quark_from_string("task_state");
4316 LTT_CHANNEL_VM_STATE
= g_quark_from_string("vm_state");
4317 LTT_CHANNEL_KPROBE_STATE
= g_quark_from_string("kprobe_state");
4318 LTT_CHANNEL_FS
= g_quark_from_string("fs");
4319 LTT_CHANNEL_KERNEL
= g_quark_from_string("kernel");
4320 LTT_CHANNEL_MM
= g_quark_from_string("mm");
4321 LTT_CHANNEL_USERSPACE
= g_quark_from_string("userspace");
4322 LTT_CHANNEL_BLOCK
= g_quark_from_string("block");
4324 LTT_EVENT_SYSCALL_ENTRY
= g_quark_from_string("syscall_entry");
4325 LTT_EVENT_SYSCALL_EXIT
= g_quark_from_string("syscall_exit");
4326 LTT_EVENT_TRAP_ENTRY
= g_quark_from_string("trap_entry");
4327 LTT_EVENT_TRAP_EXIT
= g_quark_from_string("trap_exit");
4328 LTT_EVENT_PAGE_FAULT_ENTRY
= g_quark_from_string("page_fault_entry");
4329 LTT_EVENT_PAGE_FAULT_EXIT
= g_quark_from_string("page_fault_exit");
4330 LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY
= g_quark_from_string("page_fault_nosem_entry");
4331 LTT_EVENT_PAGE_FAULT_NOSEM_EXIT
= g_quark_from_string("page_fault_nosem_exit");
4332 LTT_EVENT_IRQ_ENTRY
= g_quark_from_string("irq_entry");
4333 LTT_EVENT_IRQ_EXIT
= g_quark_from_string("irq_exit");
4334 LTT_EVENT_SOFT_IRQ_RAISE
= g_quark_from_string("softirq_raise");
4335 LTT_EVENT_SOFT_IRQ_ENTRY
= g_quark_from_string("softirq_entry");
4336 LTT_EVENT_SOFT_IRQ_EXIT
= g_quark_from_string("softirq_exit");
4337 LTT_EVENT_SCHED_SCHEDULE
= g_quark_from_string("sched_schedule");
4338 LTT_EVENT_PROCESS_FORK
= g_quark_from_string("process_fork");
4339 LTT_EVENT_KTHREAD_CREATE
= g_quark_from_string("kthread_create");
4340 LTT_EVENT_PROCESS_EXIT
= g_quark_from_string("process_exit");
4341 LTT_EVENT_PROCESS_FREE
= g_quark_from_string("process_free");
4342 LTT_EVENT_EXEC
= g_quark_from_string("exec");
4343 LTT_EVENT_PROCESS_STATE
= g_quark_from_string("process_state");
4344 LTT_EVENT_STATEDUMP_END
= g_quark_from_string("statedump_end");
4345 LTT_EVENT_FUNCTION_ENTRY
= g_quark_from_string("function_entry");
4346 LTT_EVENT_FUNCTION_EXIT
= g_quark_from_string("function_exit");
4347 LTT_EVENT_THREAD_BRAND
= g_quark_from_string("thread_brand");
4348 LTT_EVENT_REQUEST_ISSUE
= g_quark_from_string("_blk_request_issue");
4349 LTT_EVENT_REQUEST_COMPLETE
= g_quark_from_string("_blk_request_complete");
4350 LTT_EVENT_LIST_INTERRUPT
= g_quark_from_string("interrupt");
4351 LTT_EVENT_SYS_CALL_TABLE
= g_quark_from_string("sys_call_table");
4352 LTT_EVENT_SOFTIRQ_VEC
= g_quark_from_string("softirq_vec");
4353 LTT_EVENT_KPROBE_TABLE
= g_quark_from_string("kprobe_table");
4354 LTT_EVENT_KPROBE
= g_quark_from_string("kprobe");
4356 LTT_FIELD_SYSCALL_ID
= g_quark_from_string("syscall_id");
4357 LTT_FIELD_TRAP_ID
= g_quark_from_string("trap_id");
4358 LTT_FIELD_IRQ_ID
= g_quark_from_string("irq_id");
4359 LTT_FIELD_SOFT_IRQ_ID
= g_quark_from_string("softirq_id");
4360 LTT_FIELD_PREV_PID
= g_quark_from_string("prev_pid");
4361 LTT_FIELD_NEXT_PID
= g_quark_from_string("next_pid");
4362 LTT_FIELD_PREV_STATE
= g_quark_from_string("prev_state");
4363 LTT_FIELD_PARENT_PID
= g_quark_from_string("parent_pid");
4364 LTT_FIELD_CHILD_PID
= g_quark_from_string("child_pid");
4365 LTT_FIELD_PID
= g_quark_from_string("pid");
4366 LTT_FIELD_TGID
= g_quark_from_string("tgid");
4367 LTT_FIELD_CHILD_TGID
= g_quark_from_string("child_tgid");
4368 LTT_FIELD_FILENAME
= g_quark_from_string("filename");
4369 LTT_FIELD_NAME
= g_quark_from_string("name");
4370 LTT_FIELD_TYPE
= g_quark_from_string("type");
4371 LTT_FIELD_MODE
= g_quark_from_string("mode");
4372 LTT_FIELD_SUBMODE
= g_quark_from_string("submode");
4373 LTT_FIELD_STATUS
= g_quark_from_string("status");
4374 LTT_FIELD_THIS_FN
= g_quark_from_string("this_fn");
4375 LTT_FIELD_CALL_SITE
= g_quark_from_string("call_site");
4376 LTT_FIELD_MAJOR
= g_quark_from_string("major");
4377 LTT_FIELD_MINOR
= g_quark_from_string("minor");
4378 LTT_FIELD_OPERATION
= g_quark_from_string("direction");
4379 LTT_FIELD_ACTION
= g_quark_from_string("action");
4380 LTT_FIELD_ID
= g_quark_from_string("id");
4381 LTT_FIELD_ADDRESS
= g_quark_from_string("address");
4382 LTT_FIELD_SYMBOL
= g_quark_from_string("symbol");
4383 LTT_FIELD_IP
= g_quark_from_string("ip");
4385 LTTV_CPU_UNKNOWN
= g_quark_from_string("unknown");
4386 LTTV_CPU_IDLE
= g_quark_from_string("idle");
4387 LTTV_CPU_BUSY
= g_quark_from_string("busy");
4388 LTTV_CPU_IRQ
= g_quark_from_string("irq");
4389 LTTV_CPU_SOFT_IRQ
= g_quark_from_string("softirq");
4390 LTTV_CPU_TRAP
= g_quark_from_string("trap");
4392 LTTV_IRQ_UNKNOWN
= g_quark_from_string("unknown");
4393 LTTV_IRQ_IDLE
= g_quark_from_string("idle");
4394 LTTV_IRQ_BUSY
= g_quark_from_string("busy");
4396 LTTV_BDEV_UNKNOWN
= g_quark_from_string("unknown");
4397 LTTV_BDEV_IDLE
= g_quark_from_string("idle");
4398 LTTV_BDEV_BUSY_READING
= g_quark_from_string("busy_reading");
4399 LTTV_BDEV_BUSY_WRITING
= g_quark_from_string("busy_writing");
4402 static void module_destroy()
4407 LTTV_MODULE("state", "State computation", \
4408 "Update the system state, possibly saving it at intervals", \
4409 module_init
, module_destroy
)