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 if(self
->cpu_states
[i
].irq_stack
->len
)
471 g_array_remove_range(self
->cpu_states
[i
].irq_stack
, 0, self
->cpu_states
[i
].irq_stack
->len
);
472 if(self
->cpu_states
[i
].softirq_stack
->len
)
473 g_array_remove_range(self
->cpu_states
[i
].softirq_stack
, 0, self
->cpu_states
[i
].softirq_stack
->len
);
474 if(self
->cpu_states
[i
].trap_stack
->len
)
475 g_array_remove_range(self
->cpu_states
[i
].trap_stack
, 0, self
->cpu_states
[i
].trap_stack
->len
);
479 /* reset irq states */
480 for(i
=0; i
<nb_irqs
; i
++) {
481 if(self
->irq_states
[i
].mode_stack
->len
> 0)
482 g_array_remove_range(self
->irq_states
[i
].mode_stack
, 0, self
->irq_states
[i
].mode_stack
->len
);
485 /* reset softirq states */
486 for(i
=0; i
<nb_soft_irqs
; i
++) {
487 self
->soft_irq_states
[i
].pending
= 0;
488 self
->soft_irq_states
[i
].running
= 0;
491 /* reset trap states */
492 for(i
=0; i
<nb_traps
; i
++) {
493 self
->trap_states
[i
].running
= 0;
496 /* reset bdev states */
497 g_hash_table_foreach(self
->bdev_states
, bdevstate_free_cb
, NULL
);
498 //g_hash_table_steal_all(self->bdev_states);
499 g_hash_table_foreach_steal(self
->bdev_states
, rettrue
, NULL
);
502 nb_tracefile
= self
->parent
.tracefiles
->len
;
504 for(i
= 0 ; i
< nb_tracefile
; i
++) {
506 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
507 LttvTracefileContext
*, i
));
508 ltt_trace_time_span_get(self
->parent
.t
, &tfcs
->parent
.timestamp
, NULL
);
509 // tfcs->saved_position = 0;
510 tfcs
->process
= lttv_state_create_process(tfcs
, NULL
,0);
511 tfcs
->process
->state
->s
= LTTV_STATE_RUN
;
512 tfcs
->process
->last_cpu
= tfcs
->cpu_name
;
513 tfcs
->process
->last_cpu_index
= ltt_tracefile_num(((LttvTracefileContext
*)tfcs
)->tf
);
518 //static LttTime time_zero = {0,0};
520 static gint
compare_usertraces(gconstpointer a
, gconstpointer b
,
523 const LttTime
*t1
= (const LttTime
*)a
;
524 const LttTime
*t2
= (const LttTime
*)b
;
526 return ltt_time_compare(*t1
, *t2
);
529 static void free_usertrace_key(gpointer data
)
534 #define MAX_STRING_LEN 4096
537 state_load_saved_states(LttvTraceState
*tcs
)
540 GPtrArray
*quarktable
;
541 const char *trace_path
;
545 tcs
->has_precomputed_states
= FALSE
;
549 gchar buf
[MAX_STRING_LEN
];
552 trace_path
= g_quark_to_string(ltt_trace_name(tcs
->parent
.t
));
553 strncpy(path
, trace_path
, PATH_MAX
-1);
554 count
= strnlen(trace_path
, PATH_MAX
-1);
555 // quarktable : open, test
556 strncat(path
, "/precomputed/quarktable", PATH_MAX
-count
-1);
557 fp
= fopen(path
, "r");
559 quarktable
= g_ptr_array_sized_new(4096);
561 /* Index 0 is null */
563 if(hdr
== EOF
) return;
564 g_assert(hdr
== HDR_QUARKS
);
568 if(hdr
== EOF
) break;
569 g_assert(hdr
== HDR_QUARK
);
570 g_ptr_array_set_size(quarktable
, q
+1);
573 fread(&buf
[i
], sizeof(gchar
), 1, fp
);
574 if(buf
[i
] == '\0' || feof(fp
)) break;
577 len
= strnlen(buf
, MAX_STRING_LEN
-1);
578 g_ptr_array_index (quarktable
, q
) = g_new(gchar
, len
+1);
579 strncpy(g_ptr_array_index (quarktable
, q
), buf
, len
+1);
585 // saved_states : open, test
586 strncpy(path
, trace_path
, PATH_MAX
-1);
587 count
= strnlen(trace_path
, PATH_MAX
-1);
588 strncat(path
, "/precomputed/states", PATH_MAX
-count
-1);
589 fp
= fopen(path
, "r");
593 if(hdr
!= HDR_TRACE
) goto end
;
595 lttv_trace_states_read_raw(tcs
, fp
, quarktable
);
597 tcs
->has_precomputed_states
= TRUE
;
602 /* Free the quarktable */
603 for(i
=0; i
<quarktable
->len
; i
++) {
604 string
= g_ptr_array_index (quarktable
, i
);
607 g_ptr_array_free(quarktable
, TRUE
);
612 init(LttvTracesetState
*self
, LttvTraceset
*ts
)
614 guint i
, j
, nb_trace
, nb_tracefile
, nb_cpu
;
617 LttvTraceContext
*tc
;
621 LttvTracefileState
*tfcs
;
623 LttvAttributeValue v
;
625 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
626 init((LttvTracesetContext
*)self
, ts
);
628 nb_trace
= lttv_traceset_number(ts
);
629 for(i
= 0 ; i
< nb_trace
; i
++) {
630 tc
= self
->parent
.traces
[i
];
631 tcs
= LTTV_TRACE_STATE(tc
);
632 tcs
->save_interval
= LTTV_STATE_SAVE_INTERVAL
;
633 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_TRACE_STATE_USE_COUNT
,
637 if(*(v
.v_uint
) == 1) {
638 create_name_tables(tcs
);
639 create_max_time(tcs
);
641 get_name_tables(tcs
);
644 nb_tracefile
= tc
->tracefiles
->len
;
645 nb_cpu
= ltt_trace_get_num_cpu(tc
->t
);
646 nb_irq
= tcs
->nb_irqs
;
647 tcs
->processes
= NULL
;
648 tcs
->usertraces
= NULL
;
649 tcs
->running_process
= g_new(LttvProcessState
*, nb_cpu
);
651 /* init cpu resource stuff */
652 tcs
->cpu_states
= g_new(LttvCPUState
, nb_cpu
);
653 for(j
= 0; j
<nb_cpu
; j
++) {
654 tcs
->cpu_states
[j
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvCPUMode
));
655 tcs
->cpu_states
[j
].irq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
656 tcs
->cpu_states
[j
].softirq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
657 tcs
->cpu_states
[j
].trap_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
658 g_assert(tcs
->cpu_states
[j
].mode_stack
!= NULL
);
661 /* init irq resource stuff */
662 tcs
->irq_states
= g_new(LttvIRQState
, nb_irq
);
663 for(j
= 0; j
<nb_irq
; j
++) {
664 tcs
->irq_states
[j
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvIRQMode
));
665 g_assert(tcs
->irq_states
[j
].mode_stack
!= NULL
);
668 /* init soft irq stuff */
669 /* the kernel has a statically fixed max of 32 softirqs */
670 tcs
->soft_irq_states
= g_new(LttvSoftIRQState
, tcs
->nb_soft_irqs
);
672 /* init trap stuff */
673 tcs
->trap_states
= g_new(LttvTrapState
, tcs
->nb_traps
);
675 /* init bdev resource stuff */
676 tcs
->bdev_states
= g_hash_table_new(g_int_hash
, g_int_equal
);
678 restore_init_state(tcs
);
679 for(j
= 0 ; j
< nb_tracefile
; j
++) {
681 LTTV_TRACEFILE_STATE(g_array_index(tc
->tracefiles
,
682 LttvTracefileContext
*, j
));
683 tfcs
->tracefile_name
= ltt_tracefile_name(tfcs
->parent
.tf
);
684 tfcs
->cpu
= ltt_tracefile_cpu(tfcs
->parent
.tf
);
685 tfcs
->cpu_state
= &(tcs
->cpu_states
[tfcs
->cpu
]);
686 if(ltt_tracefile_tid(tfcs
->parent
.tf
) != 0) {
687 /* It's a Usertrace */
688 guint tid
= ltt_tracefile_tid(tfcs
->parent
.tf
);
689 GTree
*usertrace_tree
= (GTree
*)g_hash_table_lookup(tcs
->usertraces
,
690 GUINT_TO_POINTER(tid
));
691 if(!usertrace_tree
) {
692 usertrace_tree
= g_tree_new_full(compare_usertraces
,
693 NULL
, free_usertrace_key
, NULL
);
694 g_hash_table_insert(tcs
->usertraces
,
695 GUINT_TO_POINTER(tid
), usertrace_tree
);
697 LttTime
*timestamp
= g_new(LttTime
, 1);
698 *timestamp
= ltt_interpolate_time_from_tsc(tfcs
->parent
.tf
,
699 ltt_tracefile_creation(tfcs
->parent
.tf
));
700 g_tree_insert(usertrace_tree
, timestamp
, tfcs
);
704 /* See if the trace has saved states */
705 state_load_saved_states(tcs
);
710 fini(LttvTracesetState
*self
)
716 //LttvTracefileState *tfcs;
718 LttvAttributeValue v
;
720 nb_trace
= lttv_traceset_number(LTTV_TRACESET_CONTEXT(self
)->ts
);
721 for(i
= 0 ; i
< nb_trace
; i
++) {
722 tcs
= (LttvTraceState
*)(LTTV_TRACESET_CONTEXT(self
)->traces
[i
]);
723 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_TRACE_STATE_USE_COUNT
,
726 g_assert(*(v
.v_uint
) != 0);
729 if(*(v
.v_uint
) == 0) {
730 free_name_tables(tcs
);
732 free_saved_state(tcs
);
734 g_free(tcs
->running_process
);
735 tcs
->running_process
= NULL
;
736 lttv_state_free_process_table(tcs
->processes
);
737 lttv_state_free_usertraces(tcs
->usertraces
);
738 tcs
->processes
= NULL
;
739 tcs
->usertraces
= NULL
;
741 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
742 fini((LttvTracesetContext
*)self
);
746 static LttvTracesetContext
*
747 new_traceset_context(LttvTracesetContext
*self
)
749 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATE_TYPE
, NULL
));
753 static LttvTraceContext
*
754 new_trace_context(LttvTracesetContext
*self
)
756 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATE_TYPE
, NULL
));
760 static LttvTracefileContext
*
761 new_tracefile_context(LttvTracesetContext
*self
)
763 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATE_TYPE
, NULL
));
767 /* Write the process state of the trace */
769 static void write_process_state(gpointer key
, gpointer value
,
772 LttvProcessState
*process
;
774 LttvExecutionState
*es
;
776 FILE *fp
= (FILE *)user_data
;
781 process
= (LttvProcessState
*)value
;
783 " <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",
784 process
, process
->pid
, process
->tgid
, process
->ppid
,
785 g_quark_to_string(process
->type
),
786 process
->creation_time
.tv_sec
,
787 process
->creation_time
.tv_nsec
,
788 process
->insertion_time
.tv_sec
,
789 process
->insertion_time
.tv_nsec
,
790 g_quark_to_string(process
->name
),
791 g_quark_to_string(process
->brand
),
792 process
->cpu
, process
->free_events
);
794 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
795 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
796 fprintf(fp
, " <ES MODE=\"%s\" SUBMODE=\"%s\" ENTRY_S=%lu ENTRY_NS=%lu",
797 g_quark_to_string(es
->t
), g_quark_to_string(es
->n
),
798 es
->entry
.tv_sec
, es
->entry
.tv_nsec
);
799 fprintf(fp
, " CHANGE_S=%lu CHANGE_NS=%lu STATUS=\"%s\"/>\n",
800 es
->change
.tv_sec
, es
->change
.tv_nsec
, g_quark_to_string(es
->s
));
803 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
804 address
= g_array_index(process
->user_stack
, guint64
, i
);
805 fprintf(fp
, " <USER_STACK ADDRESS=\"%" PRIu64
"\"/>\n",
809 if(process
->usertrace
) {
810 fprintf(fp
, " <USERTRACE NAME=\"%s\" CPU=%u\n/>",
811 g_quark_to_string(process
->usertrace
->tracefile_name
),
812 process
->usertrace
->cpu
);
816 fprintf(fp
, " </PROCESS>\n");
820 void lttv_state_write(LttvTraceState
*self
, LttTime t
, FILE *fp
)
822 guint i
, nb_tracefile
, nb_block
, offset
;
825 LttvTracefileState
*tfcs
;
829 LttEventPosition
*ep
;
833 ep
= ltt_event_position_new();
835 fprintf(fp
,"<PROCESS_STATE TIME_S=%lu TIME_NS=%lu>\n", t
.tv_sec
, t
.tv_nsec
);
837 g_hash_table_foreach(self
->processes
, write_process_state
, fp
);
839 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
840 for(i
=0;i
<nb_cpus
;i
++) {
841 fprintf(fp
," <CPU NUM=%u RUNNING_PROCESS=%u>\n",
842 i
, self
->running_process
[i
]->pid
);
845 nb_tracefile
= self
->parent
.tracefiles
->len
;
847 for(i
= 0 ; i
< nb_tracefile
; i
++) {
849 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
850 LttvTracefileContext
*, i
));
851 fprintf(fp
, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
852 tfcs
->parent
.timestamp
.tv_sec
,
853 tfcs
->parent
.timestamp
.tv_nsec
);
854 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
855 if(e
== NULL
) fprintf(fp
,"/>\n");
857 ltt_event_position(e
, ep
);
858 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
859 fprintf(fp
, " BLOCK=%u OFFSET=%u TSC=%" PRIu64
"/>\n", nb_block
, offset
,
864 fprintf(fp
,"</PROCESS_STATE>\n");
868 static void write_process_state_raw(gpointer key
, gpointer value
,
871 LttvProcessState
*process
;
873 LttvExecutionState
*es
;
875 FILE *fp
= (FILE *)user_data
;
880 process
= (LttvProcessState
*)value
;
881 fputc(HDR_PROCESS
, fp
);
882 //fwrite(&header, sizeof(header), 1, fp);
883 //fprintf(fp, "%s", g_quark_to_string(process->type));
885 fwrite(&process
->type
, sizeof(process
->type
), 1, fp
);
886 //fprintf(fp, "%s", g_quark_to_string(process->name));
888 fwrite(&process
->name
, sizeof(process
->name
), 1, fp
);
889 //fprintf(fp, "%s", g_quark_to_string(process->brand));
891 fwrite(&process
->brand
, sizeof(process
->brand
), 1, fp
);
892 fwrite(&process
->pid
, sizeof(process
->pid
), 1, fp
);
893 fwrite(&process
->free_events
, sizeof(process
->free_events
), 1, fp
);
894 fwrite(&process
->tgid
, sizeof(process
->tgid
), 1, fp
);
895 fwrite(&process
->ppid
, sizeof(process
->ppid
), 1, fp
);
896 fwrite(&process
->cpu
, sizeof(process
->cpu
), 1, fp
);
897 fwrite(&process
->creation_time
, sizeof(process
->creation_time
), 1, fp
);
898 fwrite(&process
->insertion_time
, sizeof(process
->insertion_time
), 1, fp
);
902 " <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",
903 process
, process
->pid
, process
->tgid
, process
->ppid
,
904 g_quark_to_string(process
->type
),
905 process
->creation_time
.tv_sec
,
906 process
->creation_time
.tv_nsec
,
907 process
->insertion_time
.tv_sec
,
908 process
->insertion_time
.tv_nsec
,
909 g_quark_to_string(process
->name
),
910 g_quark_to_string(process
->brand
),
914 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
915 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
918 //fprintf(fp, "%s", g_quark_to_string(es->t));
920 fwrite(&es
->t
, sizeof(es
->t
), 1, fp
);
921 //fprintf(fp, "%s", g_quark_to_string(es->n));
923 fwrite(&es
->n
, sizeof(es
->n
), 1, fp
);
924 //fprintf(fp, "%s", g_quark_to_string(es->s));
926 fwrite(&es
->s
, sizeof(es
->s
), 1, fp
);
927 fwrite(&es
->entry
, sizeof(es
->entry
), 1, fp
);
928 fwrite(&es
->change
, sizeof(es
->change
), 1, fp
);
929 fwrite(&es
->cum_cpu_time
, sizeof(es
->cum_cpu_time
), 1, fp
);
931 fprintf(fp
, " <ES MODE=\"%s\" SUBMODE=\"%s\" ENTRY_S=%lu ENTRY_NS=%lu",
932 g_quark_to_string(es
->t
), g_quark_to_string(es
->n
),
933 es
->entry
.tv_sec
, es
->entry
.tv_nsec
);
934 fprintf(fp
, " CHANGE_S=%lu CHANGE_NS=%lu STATUS=\"%s\"/>\n",
935 es
->change
.tv_sec
, es
->change
.tv_nsec
, g_quark_to_string(es
->s
));
939 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
940 address
= g_array_index(process
->user_stack
, guint64
, i
);
941 fputc(HDR_USER_STACK
, fp
);
942 fwrite(&address
, sizeof(address
), 1, fp
);
944 fprintf(fp
, " <USER_STACK ADDRESS=\"%llu\"/>\n",
949 if(process
->usertrace
) {
950 fputc(HDR_USERTRACE
, fp
);
951 //fprintf(fp, "%s", g_quark_to_string(process->usertrace->tracefile_name));
953 fwrite(&process
->usertrace
->tracefile_name
,
954 sizeof(process
->usertrace
->tracefile_name
), 1, fp
);
955 fwrite(&process
->usertrace
->cpu
, sizeof(process
->usertrace
->cpu
), 1, fp
);
957 fprintf(fp
, " <USERTRACE NAME=\"%s\" CPU=%u\n/>",
958 g_quark_to_string(process
->usertrace
->tracefile_name
),
959 process
->usertrace
->cpu
);
966 void lttv_state_write_raw(LttvTraceState
*self
, LttTime t
, FILE *fp
)
968 guint i
, nb_tracefile
, nb_block
, offset
;
971 LttvTracefileState
*tfcs
;
975 LttEventPosition
*ep
;
979 ep
= ltt_event_position_new();
981 //fprintf(fp,"<PROCESS_STATE TIME_S=%lu TIME_NS=%lu>\n", t.tv_sec, t.tv_nsec);
982 fputc(HDR_PROCESS_STATE
, fp
);
983 fwrite(&t
, sizeof(t
), 1, fp
);
985 g_hash_table_foreach(self
->processes
, write_process_state_raw
, fp
);
987 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
988 for(i
=0;i
<nb_cpus
;i
++) {
990 fwrite(&i
, sizeof(i
), 1, fp
); /* cpu number */
991 fwrite(&self
->running_process
[i
]->pid
,
992 sizeof(self
->running_process
[i
]->pid
), 1, fp
);
993 //fprintf(fp," <CPU NUM=%u RUNNING_PROCESS=%u>\n",
994 // i, self->running_process[i]->pid);
997 nb_tracefile
= self
->parent
.tracefiles
->len
;
999 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1001 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1002 LttvTracefileContext
*, i
));
1003 // fprintf(fp, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
1004 // tfcs->parent.timestamp.tv_sec,
1005 // tfcs->parent.timestamp.tv_nsec);
1006 fputc(HDR_TRACEFILE
, fp
);
1007 fwrite(&tfcs
->parent
.timestamp
, sizeof(tfcs
->parent
.timestamp
), 1, fp
);
1008 /* Note : if timestamp if LTT_TIME_INFINITE, there will be no
1009 * position following : end of trace */
1010 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
1012 ltt_event_position(e
, ep
);
1013 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
1014 //fprintf(fp, " BLOCK=%u OFFSET=%u TSC=%llu/>\n", nb_block, offset,
1016 fwrite(&nb_block
, sizeof(nb_block
), 1, fp
);
1017 fwrite(&offset
, sizeof(offset
), 1, fp
);
1018 fwrite(&tsc
, sizeof(tsc
), 1, fp
);
1025 /* Read process state from a file */
1027 /* Called because a HDR_PROCESS was found */
1028 static void read_process_state_raw(LttvTraceState
*self
, FILE *fp
,
1029 GPtrArray
*quarktable
)
1031 LttvExecutionState
*es
;
1032 LttvProcessState
*process
, *parent_process
;
1033 LttvProcessState tmp
;
1038 /* TODO : check return value */
1039 fread(&tmp
.type
, sizeof(tmp
.type
), 1, fp
);
1040 fread(&tmp
.name
, sizeof(tmp
.name
), 1, fp
);
1041 fread(&tmp
.brand
, sizeof(tmp
.brand
), 1, fp
);
1042 fread(&tmp
.pid
, sizeof(tmp
.pid
), 1, fp
);
1043 fread(&tmp
.free_events
, sizeof(tmp
.free_events
), 1, fp
);
1044 fread(&tmp
.tgid
, sizeof(tmp
.tgid
), 1, fp
);
1045 fread(&tmp
.ppid
, sizeof(tmp
.ppid
), 1, fp
);
1046 fread(&tmp
.cpu
, sizeof(tmp
.cpu
), 1, fp
);
1047 fread(&tmp
.creation_time
, sizeof(tmp
.creation_time
), 1, fp
);
1048 fread(&tmp
.insertion_time
, sizeof(tmp
.insertion_time
), 1, fp
);
1051 process
= lttv_state_find_process(self
, tmp
.cpu
, tmp
.pid
);
1053 /* We must link to the parent */
1054 parent_process
= lttv_state_find_process_or_create(self
, ANY_CPU
, tmp
.ppid
,
1056 process
= lttv_state_find_process(self
, ANY_CPU
, tmp
.pid
);
1057 if(process
== NULL
) {
1058 process
= lttv_state_create_process(self
, parent_process
, tmp
.cpu
,
1060 g_quark_from_string((gchar
*)g_ptr_array_index(quarktable
, tmp
.name
)),
1061 &tmp
.creation_time
);
1064 process
->insertion_time
= tmp
.insertion_time
;
1065 process
->creation_time
= tmp
.creation_time
;
1066 process
->type
= g_quark_from_string(
1067 (gchar
*)g_ptr_array_index(quarktable
, tmp
.type
));
1068 process
->tgid
= tmp
.tgid
;
1069 process
->ppid
= tmp
.ppid
;
1070 process
->brand
= g_quark_from_string(
1071 (gchar
*)g_ptr_array_index(quarktable
, tmp
.brand
));
1073 g_quark_from_string((gchar
*)g_ptr_array_index(quarktable
, tmp
.name
));
1074 process
->free_events
= tmp
.free_events
;
1077 if(feof(fp
) || ferror(fp
)) goto end_loop
;
1079 gint hdr
= fgetc(fp
);
1080 if(hdr
== EOF
) goto end_loop
;
1084 process
->execution_stack
=
1085 g_array_set_size(process
->execution_stack
,
1086 process
->execution_stack
->len
+ 1);
1087 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
1088 process
->execution_stack
->len
-1);
1089 process
->state
= es
;
1091 fread(&es
->t
, sizeof(es
->t
), 1, fp
);
1092 es
->t
= g_quark_from_string(
1093 (gchar
*)g_ptr_array_index(quarktable
, es
->t
));
1094 fread(&es
->n
, sizeof(es
->n
), 1, fp
);
1095 es
->n
= g_quark_from_string(
1096 (gchar
*)g_ptr_array_index(quarktable
, es
->n
));
1097 fread(&es
->s
, sizeof(es
->s
), 1, fp
);
1098 es
->s
= g_quark_from_string(
1099 (gchar
*)g_ptr_array_index(quarktable
, es
->s
));
1100 fread(&es
->entry
, sizeof(es
->entry
), 1, fp
);
1101 fread(&es
->change
, sizeof(es
->change
), 1, fp
);
1102 fread(&es
->cum_cpu_time
, sizeof(es
->cum_cpu_time
), 1, fp
);
1104 case HDR_USER_STACK
:
1105 process
->user_stack
= g_array_set_size(process
->user_stack
,
1106 process
->user_stack
->len
+ 1);
1107 address
= &g_array_index(process
->user_stack
, guint64
,
1108 process
->user_stack
->len
-1);
1109 fread(address
, sizeof(address
), 1, fp
);
1110 process
->current_function
= *address
;
1113 fread(&tmpq
, sizeof(tmpq
), 1, fp
);
1114 fread(&process
->usertrace
->cpu
, sizeof(process
->usertrace
->cpu
), 1, fp
);
1126 /* Called because a HDR_PROCESS_STATE was found */
1127 /* Append a saved state to the trace states */
1128 void lttv_state_read_raw(LttvTraceState
*self
, FILE *fp
, GPtrArray
*quarktable
)
1130 guint i
, nb_tracefile
, nb_block
, offset
;
1132 LttvTracefileState
*tfcs
;
1134 LttEventPosition
*ep
;
1142 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
1144 LttvAttributeValue value
;
1145 GTree
*pqueue
= self
->parent
.ts_context
->pqueue
;
1146 ep
= ltt_event_position_new();
1148 restore_init_state(self
);
1150 fread(&t
, sizeof(t
), 1, fp
);
1153 if(feof(fp
) || ferror(fp
)) goto end_loop
;
1155 if(hdr
== EOF
) goto end_loop
;
1159 /* Call read_process_state_raw */
1160 read_process_state_raw(self
, fp
, quarktable
);
1168 case HDR_USER_STACK
:
1170 case HDR_PROCESS_STATE
:
1176 g_error("Error while parsing saved state file : unknown data header %d",
1182 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
1183 for(i
=0;i
<nb_cpus
;i
++) {
1186 g_assert(hdr
== HDR_CPU
);
1187 fread(&cpu_num
, sizeof(cpu_num
), 1, fp
); /* cpu number */
1188 g_assert(i
== cpu_num
);
1189 fread(&self
->running_process
[i
]->pid
,
1190 sizeof(self
->running_process
[i
]->pid
), 1, fp
);
1193 nb_tracefile
= self
->parent
.tracefiles
->len
;
1195 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1197 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1198 LttvTracefileContext
*, i
));
1199 // fprintf(fp, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
1200 // tfcs->parent.timestamp.tv_sec,
1201 // tfcs->parent.timestamp.tv_nsec);
1202 g_tree_remove(pqueue
, &tfcs
->parent
);
1204 g_assert(hdr
== HDR_TRACEFILE
);
1205 fread(&tfcs
->parent
.timestamp
, sizeof(tfcs
->parent
.timestamp
), 1, fp
);
1206 /* Note : if timestamp if LTT_TIME_INFINITE, there will be no
1207 * position following : end of trace */
1208 if(ltt_time_compare(tfcs
->parent
.timestamp
, ltt_time_infinite
) != 0) {
1209 fread(&nb_block
, sizeof(nb_block
), 1, fp
);
1210 fread(&offset
, sizeof(offset
), 1, fp
);
1211 fread(&tsc
, sizeof(tsc
), 1, fp
);
1212 ltt_event_position_set(ep
, tfcs
->parent
.tf
, nb_block
, offset
, tsc
);
1213 gint ret
= ltt_tracefile_seek_position(tfcs
->parent
.tf
, ep
);
1215 g_tree_insert(pqueue
, &tfcs
->parent
, &tfcs
->parent
);
1220 saved_states_tree
= lttv_attribute_find_subdir(self
->parent
.t_a
,
1221 LTTV_STATE_SAVED_STATES
);
1222 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1223 value
= lttv_attribute_add(saved_states_tree
,
1224 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
1225 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
1226 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
1227 *(value
.v_time
) = t
;
1228 lttv_state_save(self
, saved_state_tree
);
1229 g_debug("Saving state at time %lu.%lu", t
.tv_sec
,
1232 *(self
->max_time_state_recomputed_in_seek
) = t
;
1236 /* Called when a HDR_TRACE is found */
1237 void lttv_trace_states_read_raw(LttvTraceState
*tcs
, FILE *fp
,
1238 GPtrArray
*quarktable
)
1243 if(feof(fp
) || ferror(fp
)) goto end_loop
;
1245 if(hdr
== EOF
) goto end_loop
;
1248 case HDR_PROCESS_STATE
:
1249 /* Call read_process_state_raw */
1250 lttv_state_read_raw(tcs
, fp
, quarktable
);
1258 case HDR_USER_STACK
:
1262 g_error("Error while parsing saved state file :"
1263 " unexpected data header %d",
1267 g_error("Error while parsing saved state file : unknown data header %d",
1272 *(tcs
->max_time_state_recomputed_in_seek
) = tcs
->parent
.time_span
.end_time
;
1273 restore_init_state(tcs
);
1274 lttv_process_trace_seek_time(&tcs
->parent
, ltt_time_zero
);
1280 /* Copy each process from an existing hash table to a new one */
1282 static void copy_process_state(gpointer key
, gpointer value
,gpointer user_data
)
1284 LttvProcessState
*process
, *new_process
;
1286 GHashTable
*new_processes
= (GHashTable
*)user_data
;
1290 process
= (LttvProcessState
*)value
;
1291 new_process
= g_new(LttvProcessState
, 1);
1292 *new_process
= *process
;
1293 new_process
->execution_stack
= g_array_sized_new(FALSE
, FALSE
,
1294 sizeof(LttvExecutionState
), PREALLOCATED_EXECUTION_STACK
);
1295 new_process
->execution_stack
=
1296 g_array_set_size(new_process
->execution_stack
,
1297 process
->execution_stack
->len
);
1298 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
1299 g_array_index(new_process
->execution_stack
, LttvExecutionState
, i
) =
1300 g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
1302 new_process
->state
= &g_array_index(new_process
->execution_stack
,
1303 LttvExecutionState
, new_process
->execution_stack
->len
- 1);
1304 new_process
->user_stack
= g_array_sized_new(FALSE
, FALSE
,
1305 sizeof(guint64
), 0);
1306 new_process
->user_stack
=
1307 g_array_set_size(new_process
->user_stack
,
1308 process
->user_stack
->len
);
1309 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
1310 g_array_index(new_process
->user_stack
, guint64
, i
) =
1311 g_array_index(process
->user_stack
, guint64
, i
);
1313 new_process
->current_function
= process
->current_function
;
1314 g_hash_table_insert(new_processes
, new_process
, new_process
);
1318 static GHashTable
*lttv_state_copy_process_table(GHashTable
*processes
)
1320 GHashTable
*new_processes
= g_hash_table_new(process_hash
, process_equal
);
1322 g_hash_table_foreach(processes
, copy_process_state
, new_processes
);
1323 return new_processes
;
1326 static LttvCPUState
*lttv_state_copy_cpu_states(LttvCPUState
*states
, guint n
)
1329 LttvCPUState
*retval
;
1331 retval
= g_new(LttvCPUState
, n
);
1333 for(i
=0; i
<n
; i
++) {
1334 retval
[i
].irq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
1335 g_array_set_size(retval
[i
].irq_stack
, states
[i
].irq_stack
->len
);
1336 for(j
=0; j
<states
[i
].irq_stack
->len
; j
++) {
1337 g_array_index(retval
[i
].irq_stack
, gint
, j
) = g_array_index(states
[i
].irq_stack
, gint
, j
);
1340 retval
[i
].softirq_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
1341 g_array_set_size(retval
[i
].softirq_stack
, states
[i
].softirq_stack
->len
);
1342 for(j
=0; j
<states
[i
].softirq_stack
->len
; j
++) {
1343 g_array_index(retval
[i
].softirq_stack
, gint
, j
) = g_array_index(states
[i
].softirq_stack
, gint
, j
);
1346 retval
[i
].trap_stack
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
1347 g_array_set_size(retval
[i
].trap_stack
, states
[i
].trap_stack
->len
);
1348 for(j
=0; j
<states
[i
].trap_stack
->len
; j
++) {
1349 g_array_index(retval
[i
].trap_stack
, gint
, j
) = g_array_index(states
[i
].trap_stack
, gint
, j
);
1352 retval
[i
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvCPUMode
));
1353 g_array_set_size(retval
[i
].mode_stack
, states
[i
].mode_stack
->len
);
1354 for(j
=0; j
<states
[i
].mode_stack
->len
; j
++) {
1355 g_array_index(retval
[i
].mode_stack
, GQuark
, j
) = g_array_index(states
[i
].mode_stack
, GQuark
, j
);
1362 static void lttv_state_free_cpu_states(LttvCPUState
*states
, guint n
)
1366 for(i
=0; i
<n
; i
++) {
1367 g_array_free(states
[i
].mode_stack
, TRUE
);
1368 g_array_free(states
[i
].irq_stack
, TRUE
);
1369 g_array_free(states
[i
].softirq_stack
, TRUE
);
1370 g_array_free(states
[i
].trap_stack
, TRUE
);
1376 static LttvIRQState
*lttv_state_copy_irq_states(LttvIRQState
*states
, guint n
)
1379 LttvIRQState
*retval
;
1381 retval
= g_new(LttvIRQState
, n
);
1383 for(i
=0; i
<n
; i
++) {
1384 retval
[i
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvIRQMode
));
1385 g_array_set_size(retval
[i
].mode_stack
, states
[i
].mode_stack
->len
);
1386 for(j
=0; j
<states
[i
].mode_stack
->len
; j
++) {
1387 g_array_index(retval
[i
].mode_stack
, GQuark
, j
) = g_array_index(states
[i
].mode_stack
, GQuark
, j
);
1394 static void lttv_state_free_irq_states(LttvIRQState
*states
, guint n
)
1398 for(i
=0; i
<n
; i
++) {
1399 g_array_free(states
[i
].mode_stack
, TRUE
);
1405 static LttvSoftIRQState
*lttv_state_copy_soft_irq_states(LttvSoftIRQState
*states
, guint n
)
1408 LttvSoftIRQState
*retval
;
1410 retval
= g_new(LttvSoftIRQState
, n
);
1412 for(i
=0; i
<n
; i
++) {
1413 retval
[i
].pending
= states
[i
].pending
;
1414 retval
[i
].running
= states
[i
].running
;
1420 static void lttv_state_free_soft_irq_states(LttvSoftIRQState
*states
, guint n
)
1425 static LttvTrapState
*lttv_state_copy_trap_states(LttvTrapState
*states
, guint n
)
1428 LttvTrapState
*retval
;
1430 retval
= g_new(LttvTrapState
, n
);
1432 for(i
=0; i
<n
; i
++) {
1433 retval
[i
].running
= states
[i
].running
;
1439 static void lttv_state_free_trap_states(LttvTrapState
*states
, guint n
)
1444 /* bdevstate stuff */
1446 static LttvBdevState
*get_hashed_bdevstate(LttvTraceState
*ts
, guint16 devcode
)
1448 gint devcode_gint
= devcode
;
1449 gpointer bdev
= g_hash_table_lookup(ts
->bdev_states
, &devcode_gint
);
1451 LttvBdevState
*bdevstate
= g_new(LttvBdevState
, 1);
1452 bdevstate
->mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(GQuark
));
1454 gint
* key
= g_new(gint
, 1);
1456 g_hash_table_insert(ts
->bdev_states
, key
, bdevstate
);
1464 static LttvBdevState
*bdevstate_new(void)
1466 LttvBdevState
*retval
;
1467 retval
= g_new(LttvBdevState
, 1);
1468 retval
->mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(GQuark
));
1473 static void bdevstate_free(LttvBdevState
*bds
)
1475 g_array_free(bds
->mode_stack
, TRUE
);
1479 static void bdevstate_free_cb(gpointer key
, gpointer value
, gpointer user_data
)
1481 LttvBdevState
*bds
= (LttvBdevState
*) value
;
1483 bdevstate_free(bds
);
1486 static LttvBdevState
*bdevstate_copy(LttvBdevState
*bds
)
1488 LttvBdevState
*retval
;
1490 retval
= bdevstate_new();
1491 g_array_insert_vals(retval
->mode_stack
, 0, bds
->mode_stack
->data
, bds
->mode_stack
->len
);
1496 static void insert_and_copy_bdev_state(gpointer k
, gpointer v
, gpointer u
)
1498 //GHashTable *ht = (GHashTable *)u;
1499 LttvBdevState
*bds
= (LttvBdevState
*)v
;
1500 LttvBdevState
*newbds
;
1502 newbds
= bdevstate_copy(bds
);
1504 g_hash_table_insert(u
, k
, newbds
);
1507 static GHashTable
*lttv_state_copy_blkdev_hashtable(GHashTable
*ht
)
1511 retval
= g_hash_table_new(g_int_hash
, g_int_equal
);
1513 g_hash_table_foreach(ht
, insert_and_copy_bdev_state
, retval
);
1518 /* Free a hashtable and the LttvBdevState structures its values
1521 static void lttv_state_free_blkdev_hashtable(GHashTable
*ht
)
1523 g_hash_table_foreach(ht
, bdevstate_free_cb
, NULL
);
1524 g_hash_table_destroy(ht
);
1527 /* The saved state for each trace contains a member "processes", which
1528 stores a copy of the process table, and a member "tracefiles" with
1529 one entry per tracefile. Each tracefile has a "process" member pointing
1530 to the current process and a "position" member storing the tracefile
1531 position (needed to seek to the current "next" event. */
1533 static void state_save(LttvTraceState
*self
, LttvAttribute
*container
)
1535 guint i
, nb_tracefile
, nb_cpus
, nb_irqs
, nb_soft_irqs
, nb_traps
;
1537 LttvTracefileState
*tfcs
;
1539 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
1541 guint
*running_process
;
1543 LttvAttributeValue value
;
1545 LttEventPosition
*ep
;
1547 tracefiles_tree
= lttv_attribute_find_subdir(container
,
1548 LTTV_STATE_TRACEFILES
);
1550 value
= lttv_attribute_add(container
, LTTV_STATE_PROCESSES
,
1552 *(value
.v_pointer
) = lttv_state_copy_process_table(self
->processes
);
1554 /* Add the currently running processes array */
1555 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
1556 running_process
= g_new(guint
, nb_cpus
);
1557 for(i
=0;i
<nb_cpus
;i
++) {
1558 running_process
[i
] = self
->running_process
[i
]->pid
;
1560 value
= lttv_attribute_add(container
, LTTV_STATE_RUNNING_PROCESS
,
1562 *(value
.v_pointer
) = running_process
;
1564 g_info("State save");
1566 nb_tracefile
= self
->parent
.tracefiles
->len
;
1568 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1570 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1571 LttvTracefileContext
*, i
));
1572 tracefile_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1573 value
= lttv_attribute_add(tracefiles_tree
, i
,
1575 *(value
.v_gobject
) = (GObject
*)tracefile_tree
;
1577 value
= lttv_attribute_add(tracefile_tree
, LTTV_STATE_PROCESS
,
1579 *(value
.v_uint
) = tfcs
->process
->pid
;
1581 value
= lttv_attribute_add(tracefile_tree
, LTTV_STATE_EVENT
,
1583 /* Only save the position if the tfs has not infinite time. */
1584 //if(!g_tree_lookup(self->parent.ts_context->pqueue, &tfcs->parent)
1585 // && current_tfcs != tfcs) {
1586 if(ltt_time_compare(tfcs
->parent
.timestamp
, ltt_time_infinite
) == 0) {
1587 *(value
.v_pointer
) = NULL
;
1589 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
1590 ep
= ltt_event_position_new();
1591 ltt_event_position(e
, ep
);
1592 *(value
.v_pointer
) = ep
;
1594 guint nb_block
, offset
;
1597 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
1598 g_info("Block %u offset %u tsc %" PRIu64
" time %lu.%lu", nb_block
, offset
,
1600 tfcs
->parent
.timestamp
.tv_sec
, tfcs
->parent
.timestamp
.tv_nsec
);
1604 /* save the cpu state */
1606 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_CPUS_COUNT
,
1608 *(value
.v_uint
) = nb_cpus
;
1610 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_CPUS
,
1612 *(value
.v_pointer
) = lttv_state_copy_cpu_states(self
->cpu_states
, nb_cpus
);
1615 /* save the irq state */
1616 nb_irqs
= self
->nb_irqs
;
1618 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_IRQS
,
1620 *(value
.v_pointer
) = lttv_state_copy_irq_states(self
->irq_states
, nb_irqs
);
1623 /* save the soft irq state */
1624 nb_soft_irqs
= self
->nb_soft_irqs
;
1626 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_SOFT_IRQS
,
1628 *(value
.v_pointer
) = lttv_state_copy_soft_irq_states(self
->soft_irq_states
, nb_soft_irqs
);
1631 /* save the trap state */
1632 nb_traps
= self
->nb_traps
;
1634 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_TRAPS
,
1636 *(value
.v_pointer
) = lttv_state_copy_trap_states(self
->trap_states
, nb_traps
);
1639 /* save the blkdev states */
1640 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_BLKDEVS
,
1642 *(value
.v_pointer
) = lttv_state_copy_blkdev_hashtable(self
->bdev_states
);
1646 static void state_restore(LttvTraceState
*self
, LttvAttribute
*container
)
1648 guint i
, nb_tracefile
, pid
, nb_cpus
, nb_irqs
, nb_soft_irqs
, nb_traps
;
1650 LttvTracefileState
*tfcs
;
1652 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
1654 guint
*running_process
;
1656 LttvAttributeType type
;
1658 LttvAttributeValue value
;
1660 LttvAttributeName name
;
1664 LttEventPosition
*ep
;
1666 LttvTracesetContext
*tsc
= self
->parent
.ts_context
;
1668 tracefiles_tree
= lttv_attribute_find_subdir(container
,
1669 LTTV_STATE_TRACEFILES
);
1671 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_PROCESSES
,
1673 g_assert(type
== LTTV_POINTER
);
1674 lttv_state_free_process_table(self
->processes
);
1675 self
->processes
= lttv_state_copy_process_table(*(value
.v_pointer
));
1677 /* Add the currently running processes array */
1678 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
1679 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RUNNING_PROCESS
,
1681 g_assert(type
== LTTV_POINTER
);
1682 running_process
= *(value
.v_pointer
);
1683 for(i
=0;i
<nb_cpus
;i
++) {
1684 pid
= running_process
[i
];
1685 self
->running_process
[i
] = lttv_state_find_process(self
, i
, pid
);
1686 g_assert(self
->running_process
[i
] != NULL
);
1689 nb_tracefile
= self
->parent
.tracefiles
->len
;
1691 //g_tree_destroy(tsc->pqueue);
1692 //tsc->pqueue = g_tree_new(compare_tracefile);
1694 /* restore cpu resource states */
1695 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS
, &value
);
1696 g_assert(type
== LTTV_POINTER
);
1697 lttv_state_free_cpu_states(self
->cpu_states
, nb_cpus
);
1698 self
->cpu_states
= lttv_state_copy_cpu_states(*(value
.v_pointer
), nb_cpus
);
1700 /* restore irq resource states */
1701 nb_irqs
= self
->nb_irqs
;
1702 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_IRQS
, &value
);
1703 g_assert(type
== LTTV_POINTER
);
1704 lttv_state_free_irq_states(self
->irq_states
, nb_irqs
);
1705 self
->irq_states
= lttv_state_copy_irq_states(*(value
.v_pointer
), nb_irqs
);
1707 /* restore soft irq resource states */
1708 nb_soft_irqs
= self
->nb_soft_irqs
;
1709 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_SOFT_IRQS
, &value
);
1710 g_assert(type
== LTTV_POINTER
);
1711 lttv_state_free_soft_irq_states(self
->soft_irq_states
, nb_soft_irqs
);
1712 self
->soft_irq_states
= lttv_state_copy_soft_irq_states(*(value
.v_pointer
), nb_soft_irqs
);
1714 /* restore trap resource states */
1715 nb_traps
= self
->nb_traps
;
1716 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_TRAPS
, &value
);
1717 g_assert(type
== LTTV_POINTER
);
1718 lttv_state_free_trap_states(self
->trap_states
, nb_traps
);
1719 self
->trap_states
= lttv_state_copy_trap_states(*(value
.v_pointer
), nb_traps
);
1721 /* restore the blkdev states */
1722 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_BLKDEVS
, &value
);
1723 g_assert(type
== LTTV_POINTER
);
1724 lttv_state_free_blkdev_hashtable(self
->bdev_states
);
1725 self
->bdev_states
= lttv_state_copy_blkdev_hashtable(*(value
.v_pointer
));
1727 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1729 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1730 LttvTracefileContext
*, i
));
1731 type
= lttv_attribute_get(tracefiles_tree
, i
, &name
, &value
, &is_named
);
1732 g_assert(type
== LTTV_GOBJECT
);
1733 tracefile_tree
= *((LttvAttribute
**)(value
.v_gobject
));
1735 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_PROCESS
,
1737 g_assert(type
== LTTV_UINT
);
1738 pid
= *(value
.v_uint
);
1739 tfcs
->process
= lttv_state_find_process_or_create(tfcs
, pid
);
1741 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_EVENT
,
1743 g_assert(type
== LTTV_POINTER
);
1744 //g_assert(*(value.v_pointer) != NULL);
1745 ep
= *(value
.v_pointer
);
1746 g_assert(tfcs
->parent
.t_context
!= NULL
);
1748 tfcs
->cpu_state
= &self
->cpu_states
[tfcs
->cpu
];
1750 LttvTracefileContext
*tfc
= LTTV_TRACEFILE_CONTEXT(tfcs
);
1751 g_tree_remove(tsc
->pqueue
, tfc
);
1754 g_assert(ltt_tracefile_seek_position(tfc
->tf
, ep
) == 0);
1755 tfc
->timestamp
= ltt_event_time(ltt_tracefile_get_event(tfc
->tf
));
1756 g_assert(ltt_time_compare(tfc
->timestamp
, ltt_time_infinite
) != 0);
1757 g_tree_insert(tsc
->pqueue
, tfc
, tfc
);
1758 g_info("Restoring state for a tf at time %lu.%lu", tfc
->timestamp
.tv_sec
, tfc
->timestamp
.tv_nsec
);
1760 tfc
->timestamp
= ltt_time_infinite
;
1766 static void state_saved_free(LttvTraceState
*self
, LttvAttribute
*container
)
1768 guint i
, nb_tracefile
, nb_cpus
, nb_irqs
, nb_softirqs
;
1770 LttvTracefileState
*tfcs
;
1772 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
1774 guint
*running_process
;
1776 LttvAttributeType type
;
1778 LttvAttributeValue value
;
1780 LttvAttributeName name
;
1784 tracefiles_tree
= lttv_attribute_find_subdir(container
,
1785 LTTV_STATE_TRACEFILES
);
1786 g_object_ref(G_OBJECT(tracefiles_tree
));
1787 lttv_attribute_remove_by_name(container
, LTTV_STATE_TRACEFILES
);
1789 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_PROCESSES
,
1791 g_assert(type
== LTTV_POINTER
);
1792 lttv_state_free_process_table(*(value
.v_pointer
));
1793 *(value
.v_pointer
) = NULL
;
1794 lttv_attribute_remove_by_name(container
, LTTV_STATE_PROCESSES
);
1796 /* Free running processes array */
1797 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RUNNING_PROCESS
,
1799 g_assert(type
== LTTV_POINTER
);
1800 running_process
= *(value
.v_pointer
);
1801 g_free(running_process
);
1803 /* free cpu resource states */
1804 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS_COUNT
, &value
);
1805 g_assert(type
== LTTV_UINT
);
1806 nb_cpus
= *value
.v_uint
;
1807 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS
, &value
);
1808 g_assert(type
== LTTV_POINTER
);
1809 lttv_state_free_cpu_states(*(value
.v_pointer
), nb_cpus
);
1811 /* free irq resource states */
1812 nb_irqs
= self
->nb_irqs
;
1813 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_IRQS
, &value
);
1814 g_assert(type
== LTTV_POINTER
);
1815 lttv_state_free_irq_states(*(value
.v_pointer
), nb_irqs
);
1817 /* free softirq resource states */
1818 nb_softirqs
= self
->nb_irqs
;
1819 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_SOFT_IRQS
, &value
);
1820 g_assert(type
== LTTV_POINTER
);
1821 lttv_state_free_soft_irq_states(*(value
.v_pointer
), nb_softirqs
);
1823 /* free the blkdev states */
1824 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_BLKDEVS
, &value
);
1825 g_assert(type
== LTTV_POINTER
);
1826 lttv_state_free_blkdev_hashtable(*(value
.v_pointer
));
1828 nb_tracefile
= self
->parent
.tracefiles
->len
;
1830 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1832 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1833 LttvTracefileContext
*, i
));
1834 type
= lttv_attribute_get(tracefiles_tree
, i
, &name
, &value
, &is_named
);
1835 g_assert(type
== LTTV_GOBJECT
);
1836 tracefile_tree
= *((LttvAttribute
**)(value
.v_gobject
));
1838 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_EVENT
,
1840 g_assert(type
== LTTV_POINTER
);
1841 if(*(value
.v_pointer
) != NULL
) g_free(*(value
.v_pointer
));
1843 g_object_unref(G_OBJECT(tracefiles_tree
));
1847 static void free_saved_state(LttvTraceState
*self
)
1851 LttvAttributeType type
;
1853 LttvAttributeValue value
;
1855 LttvAttributeName name
;
1859 LttvAttribute
*saved_states
;
1861 saved_states
= lttv_attribute_find_subdir(self
->parent
.t_a
,
1862 LTTV_STATE_SAVED_STATES
);
1864 nb
= lttv_attribute_get_number(saved_states
);
1865 for(i
= 0 ; i
< nb
; i
++) {
1866 type
= lttv_attribute_get(saved_states
, i
, &name
, &value
, &is_named
);
1867 g_assert(type
== LTTV_GOBJECT
);
1868 state_saved_free(self
, *((LttvAttribute
**)value
.v_gobject
));
1871 lttv_attribute_remove_by_name(self
->parent
.t_a
, LTTV_STATE_SAVED_STATES
);
1876 create_max_time(LttvTraceState
*tcs
)
1878 LttvAttributeValue v
;
1880 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
1882 g_assert(*(v
.v_pointer
) == NULL
);
1883 *(v
.v_pointer
) = g_new(LttTime
,1);
1884 *((LttTime
*)*(v
.v_pointer
)) = ltt_time_zero
;
1889 get_max_time(LttvTraceState
*tcs
)
1891 LttvAttributeValue v
;
1893 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
1895 g_assert(*(v
.v_pointer
) != NULL
);
1896 tcs
->max_time_state_recomputed_in_seek
= (LttTime
*)*(v
.v_pointer
);
1901 free_max_time(LttvTraceState
*tcs
)
1903 LttvAttributeValue v
;
1905 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
1907 g_free(*(v
.v_pointer
));
1908 *(v
.v_pointer
) = NULL
;
1912 typedef struct _LttvNameTables
{
1913 // FIXME GQuark *eventtype_names;
1914 GQuark
*syscall_names
;
1920 GQuark
*soft_irq_names
;
1922 GHashTable
*kprobe_hash
;
1927 create_name_tables(LttvTraceState
*tcs
)
1931 GString
*fe_name
= g_string_new("");
1933 LttvNameTables
*name_tables
= g_new(LttvNameTables
, 1);
1935 LttvAttributeValue v
;
1939 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_NAME_TABLES
,
1941 g_assert(*(v
.v_pointer
) == NULL
);
1942 *(v
.v_pointer
) = name_tables
;
1944 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 1);
1946 if(!lttv_trace_find_hook(tcs
->parent
.t
,
1948 LTT_EVENT_SYSCALL_ENTRY
,
1949 FIELD_ARRAY(LTT_FIELD_SYSCALL_ID
),
1950 NULL
, NULL
, &hooks
)) {
1952 // th = lttv_trace_hook_get_first(&th);
1954 // t = ltt_field_type(lttv_trace_get_hook_field(th, 0));
1955 // nb = ltt_type_element_number(t);
1957 // name_tables->syscall_names = g_new(GQuark, nb);
1958 // name_tables->nb_syscalls = nb;
1960 // for(i = 0 ; i < nb ; i++) {
1961 // name_tables->syscall_names[i] = ltt_enum_string_get(t, i);
1962 // if(!name_tables->syscall_names[i]) {
1963 // GString *string = g_string_new("");
1964 // g_string_printf(string, "syscall %u", i);
1965 // name_tables->syscall_names[i] = g_quark_from_string(string->str);
1966 // g_string_free(string, TRUE);
1970 name_tables
->nb_syscalls
= 256;
1971 name_tables
->syscall_names
= g_new(GQuark
, 256);
1972 for(i
= 0 ; i
< 256 ; i
++) {
1973 g_string_printf(fe_name
, "syscall %d", i
);
1974 name_tables
->syscall_names
[i
] = g_quark_from_string(fe_name
->str
);
1977 name_tables
->syscall_names
= NULL
;
1978 name_tables
->nb_syscalls
= 0;
1980 lttv_trace_hook_remove_all(&hooks
);
1982 if(!lttv_trace_find_hook(tcs
->parent
.t
,
1984 LTT_EVENT_TRAP_ENTRY
,
1985 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
1986 NULL
, NULL
, &hooks
) ||
1987 !lttv_trace_find_hook(tcs
->parent
.t
,
1989 LTT_EVENT_PAGE_FAULT_ENTRY
,
1990 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
1991 NULL
, NULL
, &hooks
)) {
1993 // th = lttv_trace_hook_get_first(&th);
1995 // t = ltt_field_type(lttv_trace_get_hook_field(th, 0));
1996 // //nb = ltt_type_element_number(t);
1998 // name_tables->trap_names = g_new(GQuark, nb);
1999 // for(i = 0 ; i < nb ; i++) {
2000 // name_tables->trap_names[i] = g_quark_from_string(
2001 // ltt_enum_string_get(t, i));
2004 name_tables
->nb_traps
= 256;
2005 name_tables
->trap_names
= g_new(GQuark
, 256);
2006 for(i
= 0 ; i
< 256 ; i
++) {
2007 g_string_printf(fe_name
, "trap %d", i
);
2008 name_tables
->trap_names
[i
] = g_quark_from_string(fe_name
->str
);
2011 name_tables
->trap_names
= NULL
;
2012 name_tables
->nb_traps
= 0;
2014 lttv_trace_hook_remove_all(&hooks
);
2016 if(!lttv_trace_find_hook(tcs
->parent
.t
,
2018 LTT_EVENT_IRQ_ENTRY
,
2019 FIELD_ARRAY(LTT_FIELD_IRQ_ID
),
2020 NULL
, NULL
, &hooks
)) {
2023 name_tables->irq_names = g_new(GQuark, nb);
2024 for(i = 0 ; i < nb ; i++) {
2025 name_tables->irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
2029 name_tables
->nb_irqs
= 256;
2030 name_tables
->irq_names
= g_new(GQuark
, 256);
2031 for(i
= 0 ; i
< 256 ; i
++) {
2032 g_string_printf(fe_name
, "irq %d", i
);
2033 name_tables
->irq_names
[i
] = g_quark_from_string(fe_name
->str
);
2036 name_tables
->nb_irqs
= 0;
2037 name_tables
->irq_names
= NULL
;
2039 lttv_trace_hook_remove_all(&hooks
);
2041 name_tables->soft_irq_names = g_new(GQuark, nb);
2042 for(i = 0 ; i < nb ; i++) {
2043 name_tables->soft_irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
2047 /* the kernel is limited to 32 statically defined softirqs */
2048 name_tables
->nb_softirqs
= 32;
2049 name_tables
->soft_irq_names
= g_new(GQuark
, name_tables
->nb_softirqs
);
2050 for(i
= 0 ; i
< name_tables
->nb_softirqs
; i
++) {
2051 g_string_printf(fe_name
, "softirq %d", i
);
2052 name_tables
->soft_irq_names
[i
] = g_quark_from_string(fe_name
->str
);
2054 g_array_free(hooks
, TRUE
);
2056 g_string_free(fe_name
, TRUE
);
2058 #if (__SIZEOF_LONG__ == 4)
2059 name_tables
->kprobe_hash
= g_hash_table_new_full(guint64_hash
, guint64_equal
,
2062 name_tables
->kprobe_hash
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
2068 get_name_tables(LttvTraceState
*tcs
)
2070 LttvNameTables
*name_tables
;
2072 LttvAttributeValue v
;
2074 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_NAME_TABLES
,
2076 g_assert(*(v
.v_pointer
) != NULL
);
2077 name_tables
= (LttvNameTables
*)*(v
.v_pointer
);
2078 //tcs->eventtype_names = name_tables->eventtype_names;
2079 tcs
->syscall_names
= name_tables
->syscall_names
;
2080 tcs
->nb_syscalls
= name_tables
->nb_syscalls
;
2081 tcs
->trap_names
= name_tables
->trap_names
;
2082 tcs
->nb_traps
= name_tables
->nb_traps
;
2083 tcs
->irq_names
= name_tables
->irq_names
;
2084 tcs
->soft_irq_names
= name_tables
->soft_irq_names
;
2085 tcs
->nb_irqs
= name_tables
->nb_irqs
;
2086 tcs
->nb_soft_irqs
= name_tables
->nb_softirqs
;
2087 tcs
->kprobe_hash
= name_tables
->kprobe_hash
;
2092 free_name_tables(LttvTraceState
*tcs
)
2094 LttvNameTables
*name_tables
;
2096 LttvAttributeValue v
;
2098 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_NAME_TABLES
,
2100 name_tables
= (LttvNameTables
*)*(v
.v_pointer
);
2101 *(v
.v_pointer
) = NULL
;
2103 // g_free(name_tables->eventtype_names);
2104 if(name_tables
->syscall_names
) g_free(name_tables
->syscall_names
);
2105 if(name_tables
->trap_names
) g_free(name_tables
->trap_names
);
2106 if(name_tables
->irq_names
) g_free(name_tables
->irq_names
);
2107 if(name_tables
->soft_irq_names
) g_free(name_tables
->soft_irq_names
);
2108 if(name_tables
) g_free(name_tables
);
2109 if(name_tables
) g_hash_table_destroy(name_tables
->kprobe_hash
);
2112 #ifdef HASH_TABLE_DEBUG
2114 static void test_process(gpointer key
, gpointer value
, gpointer user_data
)
2116 LttvProcessState
*process
= (LttvProcessState
*)value
;
2118 /* Test for process corruption */
2119 guint stack_len
= process
->execution_stack
->len
;
2122 static void hash_table_check(GHashTable
*table
)
2124 g_hash_table_foreach(table
, test_process
, NULL
);
2130 /* clears the stack and sets the state passed as argument */
2131 static void cpu_set_base_mode(LttvCPUState
*cpust
, LttvCPUMode state
)
2133 g_array_set_size(cpust
->mode_stack
, 1);
2134 ((GQuark
*)cpust
->mode_stack
->data
)[0] = state
;
2137 static void cpu_push_mode(LttvCPUState
*cpust
, LttvCPUMode state
)
2139 g_array_set_size(cpust
->mode_stack
, cpust
->mode_stack
->len
+ 1);
2140 ((GQuark
*)cpust
->mode_stack
->data
)[cpust
->mode_stack
->len
- 1] = state
;
2143 static void cpu_pop_mode(LttvCPUState
*cpust
)
2145 if(cpust
->mode_stack
->len
<= 1)
2146 cpu_set_base_mode(cpust
, LTTV_CPU_UNKNOWN
);
2148 g_array_set_size(cpust
->mode_stack
, cpust
->mode_stack
->len
- 1);
2151 /* clears the stack and sets the state passed as argument */
2152 static void bdev_set_base_mode(LttvBdevState
*bdevst
, LttvBdevMode state
)
2154 g_array_set_size(bdevst
->mode_stack
, 1);
2155 ((GQuark
*)bdevst
->mode_stack
->data
)[0] = state
;
2158 static void bdev_push_mode(LttvBdevState
*bdevst
, LttvBdevMode state
)
2160 g_array_set_size(bdevst
->mode_stack
, bdevst
->mode_stack
->len
+ 1);
2161 ((GQuark
*)bdevst
->mode_stack
->data
)[bdevst
->mode_stack
->len
- 1] = state
;
2164 static void bdev_pop_mode(LttvBdevState
*bdevst
)
2166 if(bdevst
->mode_stack
->len
<= 1)
2167 bdev_set_base_mode(bdevst
, LTTV_BDEV_UNKNOWN
);
2169 g_array_set_size(bdevst
->mode_stack
, bdevst
->mode_stack
->len
- 1);
2172 static void irq_set_base_mode(LttvIRQState
*irqst
, LttvIRQMode state
)
2174 g_array_set_size(irqst
->mode_stack
, 1);
2175 ((GQuark
*)irqst
->mode_stack
->data
)[0] = state
;
2178 static void irq_push_mode(LttvIRQState
*irqst
, LttvIRQMode state
)
2180 g_array_set_size(irqst
->mode_stack
, irqst
->mode_stack
->len
+ 1);
2181 ((GQuark
*)irqst
->mode_stack
->data
)[irqst
->mode_stack
->len
- 1] = state
;
2184 static void irq_pop_mode(LttvIRQState
*irqst
)
2186 if(irqst
->mode_stack
->len
<= 1)
2187 irq_set_base_mode(irqst
, LTTV_IRQ_UNKNOWN
);
2189 g_array_set_size(irqst
->mode_stack
, irqst
->mode_stack
->len
- 1);
2192 static void push_state(LttvTracefileState
*tfs
, LttvExecutionMode t
,
2195 LttvExecutionState
*es
;
2197 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
2198 guint cpu
= tfs
->cpu
;
2200 #ifdef HASH_TABLE_DEBUG
2201 hash_table_check(ts
->processes
);
2203 LttvProcessState
*process
= ts
->running_process
[cpu
];
2205 guint depth
= process
->execution_stack
->len
;
2207 process
->execution_stack
=
2208 g_array_set_size(process
->execution_stack
, depth
+ 1);
2211 &g_array_index(process
->execution_stack
, LttvExecutionState
, depth
- 1);
2213 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, depth
);
2216 es
->entry
= es
->change
= tfs
->parent
.timestamp
;
2217 es
->cum_cpu_time
= ltt_time_zero
;
2218 es
->s
= process
->state
->s
;
2219 process
->state
= es
;
2223 * return 1 when empty, else 0 */
2224 int lttv_state_pop_state_cleanup(LttvProcessState
*process
,
2225 LttvTracefileState
*tfs
)
2227 guint depth
= process
->execution_stack
->len
;
2233 process
->execution_stack
=
2234 g_array_set_size(process
->execution_stack
, depth
- 1);
2235 process
->state
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
2237 process
->state
->change
= tfs
->parent
.timestamp
;
2242 static void pop_state(LttvTracefileState
*tfs
, LttvExecutionMode t
)
2244 guint cpu
= tfs
->cpu
;
2245 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
2246 LttvProcessState
*process
= ts
->running_process
[cpu
];
2248 guint depth
= process
->execution_stack
->len
;
2250 if(process
->state
->t
!= t
){
2251 g_info("Different execution mode type (%lu.%09lu): ignore it\n",
2252 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
2253 g_info("process state has %s when pop_int is %s\n",
2254 g_quark_to_string(process
->state
->t
),
2255 g_quark_to_string(t
));
2256 g_info("{ %u, %u, %s, %s, %s }\n",
2259 g_quark_to_string(process
->name
),
2260 g_quark_to_string(process
->brand
),
2261 g_quark_to_string(process
->state
->s
));
2266 g_info("Trying to pop last state on stack (%lu.%09lu): ignore it\n",
2267 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
2271 process
->execution_stack
=
2272 g_array_set_size(process
->execution_stack
, depth
- 1);
2273 process
->state
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
2275 process
->state
->change
= tfs
->parent
.timestamp
;
2278 struct search_result
{
2279 const LttTime
*time
; /* Requested time */
2280 LttTime
*best
; /* Best result */
2283 static gint
search_usertrace(gconstpointer a
, gconstpointer b
)
2285 const LttTime
*elem_time
= (const LttTime
*)a
;
2286 /* Explicit non const cast */
2287 struct search_result
*res
= (struct search_result
*)b
;
2289 if(ltt_time_compare(*elem_time
, *(res
->time
)) < 0) {
2290 /* The usertrace was created before the schedchange */
2291 /* Get larger keys */
2293 } else if(ltt_time_compare(*elem_time
, *(res
->time
)) >= 0) {
2294 /* The usertrace was created after the schedchange time */
2295 /* Get smaller keys */
2297 if(ltt_time_compare(*elem_time
, *res
->best
) < 0) {
2298 res
->best
= (LttTime
*)elem_time
;
2301 res
->best
= (LttTime
*)elem_time
;
2308 static LttvTracefileState
*ltt_state_usertrace_find(LttvTraceState
*tcs
,
2309 guint pid
, const LttTime
*timestamp
)
2311 LttvTracefileState
*tfs
= NULL
;
2312 struct search_result res
;
2313 /* Find the usertrace associated with a pid and time interval.
2314 * Search in the usertraces by PID (within a hash) and then, for each
2315 * corresponding element of the array, find the first one with creation
2316 * timestamp the lowest, but higher or equal to "timestamp". */
2317 res
.time
= timestamp
;
2319 GTree
*usertrace_tree
= g_hash_table_lookup(tcs
->usertraces
,
2320 GUINT_TO_POINTER(pid
));
2321 if(usertrace_tree
) {
2322 g_tree_search(usertrace_tree
, search_usertrace
, &res
);
2324 tfs
= g_tree_lookup(usertrace_tree
, res
.best
);
2332 lttv_state_create_process(LttvTraceState
*tcs
, LttvProcessState
*parent
,
2333 guint cpu
, guint pid
, guint tgid
, GQuark name
, const LttTime
*timestamp
)
2335 LttvProcessState
*process
= g_new(LttvProcessState
, 1);
2337 LttvExecutionState
*es
;
2342 process
->tgid
= tgid
;
2344 process
->name
= name
;
2345 process
->brand
= LTTV_STATE_UNBRANDED
;
2346 //process->last_cpu = tfs->cpu_name;
2347 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
2348 process
->type
= LTTV_STATE_USER_THREAD
;
2349 process
->usertrace
= ltt_state_usertrace_find(tcs
, pid
, timestamp
);
2350 process
->current_function
= 0; //function 0x0 by default.
2352 g_info("Process %u, core %p", process
->pid
, process
);
2353 g_hash_table_insert(tcs
->processes
, process
, process
);
2356 process
->ppid
= parent
->pid
;
2357 process
->creation_time
= *timestamp
;
2360 /* No parent. This process exists but we are missing all information about
2361 its creation. The birth time is set to zero but we remember the time of
2366 process
->creation_time
= ltt_time_zero
;
2369 process
->insertion_time
= *timestamp
;
2370 sprintf(buffer
,"%d-%lu.%lu",pid
, process
->creation_time
.tv_sec
,
2371 process
->creation_time
.tv_nsec
);
2372 process
->pid_time
= g_quark_from_string(buffer
);
2374 process
->free_events
= 0;
2375 //process->last_cpu = tfs->cpu_name;
2376 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
2377 process
->execution_stack
= g_array_sized_new(FALSE
, FALSE
,
2378 sizeof(LttvExecutionState
), PREALLOCATED_EXECUTION_STACK
);
2379 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 2);
2380 es
= process
->state
= &g_array_index(process
->execution_stack
,
2381 LttvExecutionState
, 0);
2382 es
->t
= LTTV_STATE_USER_MODE
;
2383 es
->n
= LTTV_STATE_SUBMODE_NONE
;
2384 es
->entry
= *timestamp
;
2385 //g_assert(timestamp->tv_sec != 0);
2386 es
->change
= *timestamp
;
2387 es
->cum_cpu_time
= ltt_time_zero
;
2388 es
->s
= LTTV_STATE_RUN
;
2390 es
= process
->state
= &g_array_index(process
->execution_stack
,
2391 LttvExecutionState
, 1);
2392 es
->t
= LTTV_STATE_SYSCALL
;
2393 es
->n
= LTTV_STATE_SUBMODE_NONE
;
2394 es
->entry
= *timestamp
;
2395 //g_assert(timestamp->tv_sec != 0);
2396 es
->change
= *timestamp
;
2397 es
->cum_cpu_time
= ltt_time_zero
;
2398 es
->s
= LTTV_STATE_WAIT_FORK
;
2400 /* Allocate an empty function call stack. If it's empty, use 0x0. */
2401 process
->user_stack
= g_array_sized_new(FALSE
, FALSE
,
2402 sizeof(guint64
), 0);
2407 LttvProcessState
*lttv_state_find_process(LttvTraceState
*ts
, guint cpu
,
2410 LttvProcessState key
;
2411 LttvProcessState
*process
;
2415 process
= g_hash_table_lookup(ts
->processes
, &key
);
2420 lttv_state_find_process_or_create(LttvTraceState
*ts
, guint cpu
, guint pid
,
2421 const LttTime
*timestamp
)
2423 LttvProcessState
*process
= lttv_state_find_process(ts
, cpu
, pid
);
2424 LttvExecutionState
*es
;
2426 /* Put ltt_time_zero creation time for unexisting processes */
2427 if(unlikely(process
== NULL
)) {
2428 process
= lttv_state_create_process(ts
,
2429 NULL
, cpu
, pid
, 0, LTTV_STATE_UNNAMED
, timestamp
);
2430 /* We are not sure is it's a kernel thread or normal thread, put the
2431 * bottom stack state to unknown */
2432 process
->execution_stack
=
2433 g_array_set_size(process
->execution_stack
, 1);
2434 process
->state
= es
=
2435 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
2436 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
2437 es
->s
= LTTV_STATE_UNNAMED
;
2442 /* FIXME : this function should be called when we receive an event telling that
2443 * release_task has been called in the kernel. In happens generally when
2444 * the parent waits for its child terminaison, but may also happen in special
2445 * cases in the child's exit : when the parent ignores its children SIGCCHLD or
2446 * has the flag SA_NOCLDWAIT. It can also happen when the child is part
2447 * of a killed thread group, but isn't the leader.
2449 static int exit_process(LttvTracefileState
*tfs
, LttvProcessState
*process
)
2451 LttvTraceState
*ts
= LTTV_TRACE_STATE(tfs
->parent
.t_context
);
2452 LttvProcessState key
;
2454 /* Wait for both schedule with exit dead and process free to happen.
2455 * They can happen in any order. */
2456 if (++(process
->free_events
) < 2)
2459 key
.pid
= process
->pid
;
2460 key
.cpu
= process
->cpu
;
2461 g_hash_table_remove(ts
->processes
, &key
);
2462 g_array_free(process
->execution_stack
, TRUE
);
2463 g_array_free(process
->user_stack
, TRUE
);
2469 static void free_process_state(gpointer key
, gpointer value
,gpointer user_data
)
2471 g_array_free(((LttvProcessState
*)value
)->execution_stack
, TRUE
);
2472 g_array_free(((LttvProcessState
*)value
)->user_stack
, TRUE
);
2477 static void lttv_state_free_process_table(GHashTable
*processes
)
2479 g_hash_table_foreach(processes
, free_process_state
, NULL
);
2480 g_hash_table_destroy(processes
);
2484 static gboolean
syscall_entry(void *hook_data
, void *call_data
)
2486 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2488 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2489 LttvProcessState
*process
= ts
->running_process
[cpu
];
2490 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2491 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2492 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2493 LttvExecutionSubmode submode
;
2495 guint syscall
= ltt_event_get_unsigned(e
, f
);
2496 expand_syscall_table(ts
, syscall
);
2497 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->syscall_names
[syscall
];
2498 /* There can be no system call from PID 0 : unknown state */
2499 if(process
->pid
!= 0)
2500 push_state(s
, LTTV_STATE_SYSCALL
, submode
);
2505 static gboolean
syscall_exit(void *hook_data
, void *call_data
)
2507 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2509 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2510 LttvProcessState
*process
= ts
->running_process
[cpu
];
2512 /* There can be no system call from PID 0 : unknown state */
2513 if(process
->pid
!= 0)
2514 pop_state(s
, LTTV_STATE_SYSCALL
);
2519 static gboolean
trap_entry(void *hook_data
, void *call_data
)
2521 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2522 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2523 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2524 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2525 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2527 LttvExecutionSubmode submode
;
2529 guint64 trap
= ltt_event_get_long_unsigned(e
, f
);
2531 expand_trap_table(ts
, trap
);
2533 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->trap_names
[trap
];
2535 push_state(s
, LTTV_STATE_TRAP
, submode
);
2537 /* update cpu status */
2538 cpu_push_mode(s
->cpu_state
, LTTV_CPU_TRAP
);
2540 /* update trap status */
2541 g_array_append_val(s
->cpu_state
->trap_stack
, trap
);
2542 ts
->trap_states
[trap
].running
++;
2547 static gboolean
trap_exit(void *hook_data
, void *call_data
)
2549 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2550 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2552 pop_state(s
, LTTV_STATE_TRAP
);
2554 /* update cpu status */
2555 cpu_pop_mode(s
->cpu_state
);
2557 /* update trap status */
2558 if (s
->cpu_state
->trap_stack
->len
> 0) {
2559 gint last
= g_array_index(s
->cpu_state
->trap_stack
, gint
, s
->cpu_state
->trap_stack
->len
-1);
2560 if(ts
->trap_states
[last
].running
)
2561 ts
->trap_states
[last
].running
--;
2562 g_array_remove_index(s
->cpu_state
->trap_stack
, s
->cpu_state
->trap_stack
->len
-1);
2567 static gboolean
irq_entry(void *hook_data
, void *call_data
)
2569 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2570 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2571 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2572 //guint8 ev_id = ltt_event_eventtype_id(e);
2573 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2574 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2576 LttvExecutionSubmode submode
;
2577 guint64 irq
= ltt_event_get_long_unsigned(e
, f
);
2579 expand_irq_table(ts
, irq
);
2581 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->irq_names
[irq
];
2583 /* Do something with the info about being in user or system mode when int? */
2584 push_state(s
, LTTV_STATE_IRQ
, submode
);
2586 /* update cpu status */
2587 cpu_push_mode(s
->cpu_state
, LTTV_CPU_IRQ
);
2589 /* update irq status */
2590 g_array_append_val(s
->cpu_state
->irq_stack
, irq
);
2591 irq_push_mode(&ts
->irq_states
[irq
], LTTV_IRQ_BUSY
);
2596 static gboolean
soft_irq_exit(void *hook_data
, void *call_data
)
2598 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2599 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2601 pop_state(s
, LTTV_STATE_SOFT_IRQ
);
2603 /* update cpu status */
2604 cpu_pop_mode(s
->cpu_state
);
2606 /* update softirq status */
2607 if (s
->cpu_state
->softirq_stack
->len
> 0) {
2608 gint last
= g_array_index(s
->cpu_state
->softirq_stack
, gint
, s
->cpu_state
->softirq_stack
->len
-1);
2609 if(ts
->soft_irq_states
[last
].running
)
2610 ts
->soft_irq_states
[last
].running
--;
2611 g_array_remove_index(s
->cpu_state
->softirq_stack
, s
->cpu_state
->softirq_stack
->len
-1);
2616 static gboolean
irq_exit(void *hook_data
, void *call_data
)
2618 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2619 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2621 pop_state(s
, LTTV_STATE_IRQ
);
2623 /* update cpu status */
2624 cpu_pop_mode(s
->cpu_state
);
2626 /* update irq status */
2627 if (s
->cpu_state
->irq_stack
->len
> 0) {
2628 gint last
= g_array_index(s
->cpu_state
->irq_stack
, gint
, s
->cpu_state
->irq_stack
->len
-1);
2629 g_array_remove_index(s
->cpu_state
->irq_stack
, s
->cpu_state
->irq_stack
->len
-1);
2630 irq_pop_mode(&ts
->irq_states
[last
]);
2636 static gboolean
soft_irq_raise(void *hook_data
, void *call_data
)
2638 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2639 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2640 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2641 //guint8 ev_id = ltt_event_eventtype_id(e);
2642 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2643 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2645 LttvExecutionSubmode submode
;
2646 guint64 softirq
= ltt_event_get_long_unsigned(e
, f
);
2647 guint64 nb_softirqs
= ((LttvTraceState
*)(s
->parent
.t_context
))->nb_soft_irqs
;
2649 if(softirq
< nb_softirqs
) {
2650 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->soft_irq_names
[softirq
];
2652 /* Fixup an incomplete irq table */
2653 GString
*string
= g_string_new("");
2654 g_string_printf(string
, "softirq %" PRIu64
, softirq
);
2655 submode
= g_quark_from_string(string
->str
);
2656 g_string_free(string
, TRUE
);
2659 /* update softirq status */
2660 /* a soft irq raises are not cumulative */
2661 ts
->soft_irq_states
[softirq
].pending
=1;
2666 static gboolean
soft_irq_entry(void *hook_data
, void *call_data
)
2668 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2669 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2670 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2671 //guint8 ev_id = ltt_event_eventtype_id(e);
2672 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2673 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2674 LttvExecutionSubmode submode
;
2675 guint64 softirq
= ltt_event_get_long_unsigned(e
, f
);
2676 expand_soft_irq_table(ts
, softirq
);
2677 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->soft_irq_names
[softirq
];
2679 /* Do something with the info about being in user or system mode when int? */
2680 push_state(s
, LTTV_STATE_SOFT_IRQ
, submode
);
2682 /* update cpu status */
2683 cpu_push_mode(s
->cpu_state
, LTTV_CPU_SOFT_IRQ
);
2685 /* update softirq status */
2686 g_array_append_val(s
->cpu_state
->softirq_stack
, softirq
);
2687 if(ts
->soft_irq_states
[softirq
].pending
)
2688 ts
->soft_irq_states
[softirq
].pending
--;
2689 ts
->soft_irq_states
[softirq
].running
++;
2694 static gboolean
enum_interrupt(void *hook_data
, void *call_data
)
2696 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2697 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2698 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2699 //guint8 ev_id = ltt_event_eventtype_id(e);
2700 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2702 GQuark action
= g_quark_from_string(ltt_event_get_string(e
,
2703 lttv_trace_get_hook_field(th
, 0)));
2704 guint irq
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
2706 expand_irq_table(ts
, irq
);
2707 ts
->irq_names
[irq
] = action
;
2713 static gboolean
bdev_request_issue(void *hook_data
, void *call_data
)
2715 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2716 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2717 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2718 //guint8 ev_id = ltt_event_eventtype_id(e);
2719 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2721 guint major
= ltt_event_get_long_unsigned(e
,
2722 lttv_trace_get_hook_field(th
, 0));
2723 guint minor
= ltt_event_get_long_unsigned(e
,
2724 lttv_trace_get_hook_field(th
, 1));
2725 guint oper
= ltt_event_get_long_unsigned(e
,
2726 lttv_trace_get_hook_field(th
, 2));
2727 guint16 devcode
= MKDEV(major
,minor
);
2729 /* have we seen this block device before? */
2730 gpointer bdev
= get_hashed_bdevstate(ts
, devcode
);
2733 bdev_push_mode(bdev
, LTTV_BDEV_BUSY_READING
);
2735 bdev_push_mode(bdev
, LTTV_BDEV_BUSY_WRITING
);
2740 static gboolean
bdev_request_complete(void *hook_data
, void *call_data
)
2742 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2743 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2744 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2745 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2747 guint major
= ltt_event_get_long_unsigned(e
,
2748 lttv_trace_get_hook_field(th
, 0));
2749 guint minor
= ltt_event_get_long_unsigned(e
,
2750 lttv_trace_get_hook_field(th
, 1));
2751 //guint oper = ltt_event_get_long_unsigned(e,
2752 // lttv_trace_get_hook_field(th, 2));
2753 guint16 devcode
= MKDEV(major
,minor
);
2755 /* have we seen this block device before? */
2756 gpointer bdev
= get_hashed_bdevstate(ts
, devcode
);
2758 /* update block device */
2759 bdev_pop_mode(bdev
);
2764 static void push_function(LttvTracefileState
*tfs
, guint64 funcptr
)
2768 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
2769 guint cpu
= tfs
->cpu
;
2770 LttvProcessState
*process
= ts
->running_process
[cpu
];
2772 guint depth
= process
->user_stack
->len
;
2774 process
->user_stack
=
2775 g_array_set_size(process
->user_stack
, depth
+ 1);
2777 new_func
= &g_array_index(process
->user_stack
, guint64
, depth
);
2778 *new_func
= funcptr
;
2779 process
->current_function
= funcptr
;
2782 static void pop_function(LttvTracefileState
*tfs
, guint64 funcptr
)
2784 guint cpu
= tfs
->cpu
;
2785 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
2786 LttvProcessState
*process
= ts
->running_process
[cpu
];
2788 if(process
->current_function
!= funcptr
){
2789 g_info("Different functions (%lu.%09lu): ignore it\n",
2790 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
2791 g_info("process state has %" PRIu64
" when pop_function is %" PRIu64
"\n",
2792 process
->current_function
, funcptr
);
2793 g_info("{ %u, %u, %s, %s, %s }\n",
2796 g_quark_to_string(process
->name
),
2797 g_quark_to_string(process
->brand
),
2798 g_quark_to_string(process
->state
->s
));
2801 guint depth
= process
->user_stack
->len
;
2804 g_info("Trying to pop last function on stack (%lu.%09lu): ignore it\n",
2805 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
2809 process
->user_stack
=
2810 g_array_set_size(process
->user_stack
, depth
- 1);
2811 process
->current_function
=
2812 g_array_index(process
->user_stack
, guint64
, depth
- 2);
2816 static gboolean
function_entry(void *hook_data
, void *call_data
)
2818 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2819 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2820 //guint8 ev_id = ltt_event_eventtype_id(e);
2821 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2822 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2823 guint64 funcptr
= ltt_event_get_long_unsigned(e
, f
);
2825 push_function(s
, funcptr
);
2829 static gboolean
function_exit(void *hook_data
, void *call_data
)
2831 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2832 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2833 //guint8 ev_id = ltt_event_eventtype_id(e);
2834 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2835 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
2836 guint64 funcptr
= ltt_event_get_long_unsigned(e
, f
);
2838 pop_function(s
, funcptr
);
2842 static gboolean
dump_syscall(void *hook_data
, void *call_data
)
2844 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2845 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2846 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2847 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2852 id
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2853 address
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
2854 symbol
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 2));
2856 expand_syscall_table(ts
, id
);
2857 ts
->syscall_names
[id
] = g_quark_from_string(symbol
);
2862 static gboolean
dump_kprobe(void *hook_data
, void *call_data
)
2864 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2865 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2866 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2867 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2871 ip
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2872 symbol
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 1));
2874 expand_kprobe_table(ts
, ip
, symbol
);
2879 static gboolean
dump_softirq(void *hook_data
, void *call_data
)
2881 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2882 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2883 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2884 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2889 id
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2890 address
= ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
2891 symbol
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 2));
2893 expand_soft_irq_table(ts
, id
);
2894 ts
->soft_irq_names
[id
] = g_quark_from_string(symbol
);
2899 static gboolean
schedchange(void *hook_data
, void *call_data
)
2901 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2903 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2904 LttvProcessState
*process
= ts
->running_process
[cpu
];
2905 //LttvProcessState *old_process = ts->running_process[cpu];
2907 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2908 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2909 guint pid_in
, pid_out
;
2912 pid_out
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
2913 pid_in
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
2914 state_out
= ltt_event_get_long_int(e
, lttv_trace_get_hook_field(th
, 2));
2916 if(likely(process
!= NULL
)) {
2918 /* We could not know but it was not the idle process executing.
2919 This should only happen at the beginning, before the first schedule
2920 event, and when the initial information (current process for each CPU)
2921 is missing. It is not obvious how we could, after the fact, compensate
2922 the wrongly attributed statistics. */
2924 //This test only makes sense once the state is known and if there is no
2925 //missing events. We need to silently ignore schedchange coming after a
2926 //process_free, or it causes glitches. (FIXME)
2927 //if(unlikely(process->pid != pid_out)) {
2928 // g_assert(process->pid == 0);
2930 if(process
->pid
== 0
2931 && process
->state
->t
== LTTV_STATE_MODE_UNKNOWN
) {
2933 /* Scheduling out of pid 0 at beginning of the trace :
2934 * we know for sure it is in syscall mode at this point. */
2935 g_assert(process
->execution_stack
->len
== 1);
2936 process
->state
->t
= LTTV_STATE_SYSCALL
;
2937 process
->state
->s
= LTTV_STATE_WAIT
;
2938 process
->state
->change
= s
->parent
.timestamp
;
2939 process
->state
->entry
= s
->parent
.timestamp
;
2942 if(unlikely(process
->state
->s
== LTTV_STATE_EXIT
)) {
2943 process
->state
->s
= LTTV_STATE_ZOMBIE
;
2944 process
->state
->change
= s
->parent
.timestamp
;
2946 if(unlikely(state_out
== 0)) process
->state
->s
= LTTV_STATE_WAIT_CPU
;
2947 else process
->state
->s
= LTTV_STATE_WAIT
;
2948 process
->state
->change
= s
->parent
.timestamp
;
2951 if(state_out
== 32 || state_out
== 64) { /* EXIT_DEAD || TASK_DEAD */
2952 /* see sched.h for states */
2953 if (!exit_process(s
, process
)) {
2954 process
->state
->s
= LTTV_STATE_DEAD
;
2955 process
->state
->change
= s
->parent
.timestamp
;
2960 process
= ts
->running_process
[cpu
] =
2961 lttv_state_find_process_or_create(
2962 (LttvTraceState
*)s
->parent
.t_context
,
2964 &s
->parent
.timestamp
);
2965 process
->state
->s
= LTTV_STATE_RUN
;
2967 if(process
->usertrace
)
2968 process
->usertrace
->cpu
= cpu
;
2969 // process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)s)->tf);
2970 process
->state
->change
= s
->parent
.timestamp
;
2972 /* update cpu status */
2974 /* going to idle task */
2975 cpu_set_base_mode(s
->cpu_state
, LTTV_CPU_IDLE
);
2977 /* scheduling a real task.
2978 * we must be careful here:
2979 * if we just schedule()'ed to a process that is
2980 * in a trap, we must put the cpu in trap mode
2982 cpu_set_base_mode(s
->cpu_state
, LTTV_CPU_BUSY
);
2983 if(process
->state
->t
== LTTV_STATE_TRAP
)
2984 cpu_push_mode(s
->cpu_state
, LTTV_CPU_TRAP
);
2990 static gboolean
process_fork(void *hook_data
, void *call_data
)
2992 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2993 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2994 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
2996 guint child_pid
; /* In the Linux Kernel, there is one PID per thread. */
2997 guint child_tgid
; /* tgid in the Linux kernel is the "real" POSIX PID. */
2998 //LttvProcessState *zombie_process;
3000 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3001 LttvProcessState
*process
= ts
->running_process
[cpu
];
3002 LttvProcessState
*child_process
;
3003 struct marker_field
*f
;
3006 parent_pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
3009 child_pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
3010 s
->parent
.target_pid
= child_pid
;
3013 f
= lttv_trace_get_hook_field(th
, 2);
3015 child_tgid
= ltt_event_get_unsigned(e
, f
);
3019 /* Mathieu : it seems like the process might have been scheduled in before the
3020 * fork, and, in a rare case, might be the current process. This might happen
3021 * in a SMP case where we don't have enough precision on the clocks.
3023 * Test reenabled after precision fixes on time. (Mathieu) */
3025 zombie_process
= lttv_state_find_process(ts
, ANY_CPU
, child_pid
);
3027 if(unlikely(zombie_process
!= NULL
)) {
3028 /* Reutilisation of PID. Only now we are sure that the old PID
3029 * has been released. FIXME : should know when release_task happens instead.
3031 guint num_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
3033 for(i
=0; i
< num_cpus
; i
++) {
3034 g_assert(zombie_process
!= ts
->running_process
[i
]);
3037 exit_process(s
, zombie_process
);
3040 g_assert(process
->pid
!= child_pid
);
3041 // FIXME : Add this test in the "known state" section
3042 // g_assert(process->pid == parent_pid);
3043 child_process
= lttv_state_find_process(ts
, ANY_CPU
, child_pid
);
3044 if(child_process
== NULL
) {
3045 child_process
= lttv_state_create_process(ts
, process
, cpu
,
3046 child_pid
, child_tgid
,
3047 LTTV_STATE_UNNAMED
, &s
->parent
.timestamp
);
3049 /* The process has already been created : due to time imprecision between
3050 * multiple CPUs : it has been scheduled in before creation. Note that we
3051 * shouldn't have this kind of imprecision.
3053 * Simply put a correct parent.
3055 g_error("Process %u has been created at [%lu.%09lu] "
3056 "and inserted at [%lu.%09lu] before \n"
3057 "fork on cpu %u[%lu.%09lu].\n"
3058 "Probably an unsynchronized TSC problem on the traced machine.",
3060 child_process
->creation_time
.tv_sec
,
3061 child_process
->creation_time
.tv_nsec
,
3062 child_process
->insertion_time
.tv_sec
,
3063 child_process
->insertion_time
.tv_nsec
,
3064 cpu
, ltt_event_time(e
).tv_sec
, ltt_event_time(e
).tv_nsec
);
3065 //g_assert(0); /* This is a problematic case : the process has been created
3066 // before the fork event */
3067 child_process
->ppid
= process
->pid
;
3068 child_process
->tgid
= child_tgid
;
3070 g_assert(child_process
->name
== LTTV_STATE_UNNAMED
);
3071 child_process
->name
= process
->name
;
3072 child_process
->brand
= process
->brand
;
3077 /* We stamp a newly created process as kernel_thread.
3078 * The thread should not be running yet. */
3079 static gboolean
process_kernel_thread(void *hook_data
, void *call_data
)
3081 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3082 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3083 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3085 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3086 LttvProcessState
*process
;
3087 LttvExecutionState
*es
;
3090 pid
= (guint
)ltt_event_get_long_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
3091 s
->parent
.target_pid
= pid
;
3093 process
= lttv_state_find_process_or_create(ts
, ANY_CPU
, pid
,
3095 if (process
->state
->s
!= LTTV_STATE_DEAD
) {
3096 process
->execution_stack
=
3097 g_array_set_size(process
->execution_stack
, 1);
3098 es
= process
->state
=
3099 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3100 es
->t
= LTTV_STATE_SYSCALL
;
3102 process
->type
= LTTV_STATE_KERNEL_THREAD
;
3107 static gboolean
process_exit(void *hook_data
, void *call_data
)
3109 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3110 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3111 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3113 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3114 LttvProcessState
*process
; // = ts->running_process[cpu];
3116 pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
3117 s
->parent
.target_pid
= pid
;
3119 // FIXME : Add this test in the "known state" section
3120 // g_assert(process->pid == pid);
3122 process
= lttv_state_find_process(ts
, ANY_CPU
, pid
);
3123 if(likely(process
!= NULL
)) {
3124 process
->state
->s
= LTTV_STATE_EXIT
;
3129 static gboolean
process_free(void *hook_data
, void *call_data
)
3131 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3132 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3133 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3134 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3136 LttvProcessState
*process
;
3138 /* PID of the process to release */
3139 release_pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
3140 s
->parent
.target_pid
= release_pid
;
3142 g_assert(release_pid
!= 0);
3144 process
= lttv_state_find_process(ts
, ANY_CPU
, release_pid
);
3145 if(likely(process
!= NULL
))
3146 exit_process(s
, process
);
3149 if(likely(process
!= NULL
)) {
3150 /* release_task is happening at kernel level : we can now safely release
3151 * the data structure of the process */
3152 //This test is fun, though, as it may happen that
3153 //at time t : CPU 0 : process_free
3154 //at time t+150ns : CPU 1 : schedule out
3155 //Clearly due to time imprecision, we disable it. (Mathieu)
3156 //If this weird case happen, we have no choice but to put the
3157 //Currently running process on the cpu to 0.
3158 //I re-enable it following time precision fixes. (Mathieu)
3159 //Well, in the case where an process is freed by a process on another CPU
3160 //and still scheduled, it happens that this is the schedchange that will
3161 //drop the last reference count. Do not free it here!
3162 guint num_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
3164 for(i
=0; i
< num_cpus
; i
++) {
3165 //g_assert(process != ts->running_process[i]);
3166 if(process
== ts
->running_process
[i
]) {
3167 //ts->running_process[i] = lttv_state_find_process(ts, i, 0);
3171 if(i
== num_cpus
) /* process is not scheduled */
3172 exit_process(s
, process
);
3179 static gboolean
process_exec(void *hook_data
, void *call_data
)
3181 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3182 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3183 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3184 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3187 LttvProcessState
*process
= ts
->running_process
[cpu
];
3189 #if 0//how to use a sequence that must be transformed in a string
3190 /* PID of the process to release */
3191 guint64 name_len
= ltt_event_field_element_number(e
,
3192 lttv_trace_get_hook_field(th
, 0));
3193 //name = ltt_event_get_string(e, lttv_trace_get_hook_field(th, 0));
3194 LttField
*child
= ltt_event_field_element_select(e
,
3195 lttv_trace_get_hook_field(th
, 0), 0);
3197 (gchar
*)(ltt_event_data(e
)+ltt_event_field_offset(e
, child
));
3198 gchar
*null_term_name
= g_new(gchar
, name_len
+1);
3199 memcpy(null_term_name
, name_begin
, name_len
);
3200 null_term_name
[name_len
] = '\0';
3201 process
->name
= g_quark_from_string(null_term_name
);
3204 process
->name
= g_quark_from_string(ltt_event_get_string(e
,
3205 lttv_trace_get_hook_field(th
, 0)));
3206 process
->brand
= LTTV_STATE_UNBRANDED
;
3207 //g_free(null_term_name);
3211 static gboolean
thread_brand(void *hook_data
, void *call_data
)
3213 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3214 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3215 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3216 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3219 LttvProcessState
*process
= ts
->running_process
[cpu
];
3221 name
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 0));
3222 process
->brand
= g_quark_from_string(name
);
3227 static void fix_process(gpointer key
, gpointer value
,
3230 LttvProcessState
*process
;
3231 LttvExecutionState
*es
;
3232 process
= (LttvProcessState
*)value
;
3233 LttTime
*timestamp
= (LttTime
*)user_data
;
3235 if(process
->type
== LTTV_STATE_KERNEL_THREAD
) {
3236 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3237 if(es
->t
== LTTV_STATE_MODE_UNKNOWN
) {
3238 es
->t
= LTTV_STATE_SYSCALL
;
3239 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3240 es
->entry
= *timestamp
;
3241 es
->change
= *timestamp
;
3242 es
->cum_cpu_time
= ltt_time_zero
;
3243 if(es
->s
== LTTV_STATE_UNNAMED
)
3244 es
->s
= LTTV_STATE_WAIT
;
3247 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3248 if(es
->t
== LTTV_STATE_MODE_UNKNOWN
) {
3249 es
->t
= LTTV_STATE_USER_MODE
;
3250 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3251 es
->entry
= *timestamp
;
3252 //g_assert(timestamp->tv_sec != 0);
3253 es
->change
= *timestamp
;
3254 es
->cum_cpu_time
= ltt_time_zero
;
3255 if(es
->s
== LTTV_STATE_UNNAMED
)
3256 es
->s
= LTTV_STATE_RUN
;
3258 if(process
->execution_stack
->len
== 1) {
3259 /* Still in bottom unknown mode, means never did a system call
3260 * May be either in user mode, syscall mode, running or waiting.*/
3261 /* FIXME : we may be tagging syscall mode when being user mode */
3262 process
->execution_stack
=
3263 g_array_set_size(process
->execution_stack
, 2);
3264 es
= process
->state
= &g_array_index(process
->execution_stack
,
3265 LttvExecutionState
, 1);
3266 es
->t
= LTTV_STATE_SYSCALL
;
3267 es
->n
= LTTV_STATE_SUBMODE_NONE
;
3268 es
->entry
= *timestamp
;
3269 //g_assert(timestamp->tv_sec != 0);
3270 es
->change
= *timestamp
;
3271 es
->cum_cpu_time
= ltt_time_zero
;
3272 if(es
->s
== LTTV_STATE_WAIT_FORK
)
3273 es
->s
= LTTV_STATE_WAIT
;
3279 static gboolean
statedump_end(void *hook_data
, void *call_data
)
3281 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3282 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3283 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
3284 //LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
3285 //LttvTraceHook *th = (LttvTraceHook *)hook_data;
3287 /* For all processes */
3288 /* if kernel thread, if stack[0] is unknown, set to syscall mode, wait */
3289 /* else, if stack[0] is unknown, set to user mode, running */
3291 g_hash_table_foreach(ts
->processes
, fix_process
, &tfc
->timestamp
);
3296 static gboolean
enum_process_state(void *hook_data
, void *call_data
)
3298 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
3299 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
3300 //It's slow : optimise later by doing this before reading trace.
3301 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
3307 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
3308 LttvProcessState
*process
= ts
->running_process
[cpu
];
3309 LttvProcessState
*parent_process
;
3310 struct marker_field
*f
;
3311 GQuark type
, mode
, submode
, status
;
3312 LttvExecutionState
*es
;
3316 pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
3317 s
->parent
.target_pid
= pid
;
3320 parent_pid
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
3323 command
= ltt_event_get_string(e
, lttv_trace_get_hook_field(th
, 2));
3326 f
= lttv_trace_get_hook_field(th
, 3);
3327 type
= ltt_enum_string_get(f
, ltt_event_get_unsigned(e
, f
));
3329 //FIXME: type is rarely used, enum must match possible types.
3332 f
= lttv_trace_get_hook_field(th
, 4);
3333 mode
= ltt_enum_string_get(f
,ltt_event_get_unsigned(e
, f
));
3336 f
= lttv_trace_get_hook_field(th
, 5);
3337 submode
= ltt_enum_string_get(f
, ltt_event_get_unsigned(e
, f
));
3340 f
= lttv_trace_get_hook_field(th
, 6);
3341 status
= ltt_enum_string_get(f
, ltt_event_get_unsigned(e
, f
));
3344 f
= lttv_trace_get_hook_field(th
, 7);
3346 tgid
= ltt_event_get_unsigned(e
, f
);
3351 nb_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
3352 for(i
=0; i
<nb_cpus
; i
++) {
3353 process
= lttv_state_find_process(ts
, i
, pid
);
3354 g_assert(process
!= NULL
);
3356 process
->ppid
= parent_pid
;
3357 process
->tgid
= tgid
;
3358 process
->name
= g_quark_from_string(command
);
3360 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3361 process
->type
= LTTV_STATE_KERNEL_THREAD
;
3365 /* The process might exist if a process was forked while performing the
3367 process
= lttv_state_find_process(ts
, ANY_CPU
, pid
);
3368 if(process
== NULL
) {
3369 parent_process
= lttv_state_find_process(ts
, ANY_CPU
, parent_pid
);
3370 process
= lttv_state_create_process(ts
, parent_process
, cpu
,
3371 pid
, tgid
, g_quark_from_string(command
),
3372 &s
->parent
.timestamp
);
3374 /* Keep the stack bottom : a running user mode */
3375 /* Disabled because of inconsistencies in the current statedump states. */
3376 if(type
== LTTV_STATE_KERNEL_THREAD
) {
3377 /* Only keep the bottom
3378 * FIXME Kernel thread : can be in syscall or interrupt or trap. */
3379 /* Will cause expected trap when in fact being syscall (even after end of
3381 * Will cause expected interrupt when being syscall. (only before end of
3382 * statedump event) */
3383 // This will cause a "popping last state on stack, ignoring it."
3384 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 1);
3385 es
= process
->state
= &g_array_index(process
->execution_stack
,
3386 LttvExecutionState
, 0);
3387 process
->type
= LTTV_STATE_KERNEL_THREAD
;
3388 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
3389 es
->s
= LTTV_STATE_UNNAMED
;
3390 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3392 es
->t
= LTTV_STATE_SYSCALL
;
3397 /* User space process :
3398 * bottom : user mode
3399 * either currently running or scheduled out.
3400 * can be scheduled out because interrupted in (user mode or in syscall)
3401 * or because of an explicit call to the scheduler in syscall. Note that
3402 * the scheduler call comes after the irq_exit, so never in interrupt
3404 // temp workaround : set size to 1 : only have user mode bottom of stack.
3405 // will cause g_info message of expected syscall mode when in fact being
3406 // in user mode. Can also cause expected trap when in fact being user
3407 // mode in the event of a page fault reenabling interrupts in the handler.
3408 // Expected syscall and trap can also happen after the end of statedump
3409 // This will cause a "popping last state on stack, ignoring it."
3410 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 1);
3411 es
= process
->state
= &g_array_index(process
->execution_stack
,
3412 LttvExecutionState
, 0);
3413 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
3414 es
->s
= LTTV_STATE_UNNAMED
;
3415 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3417 es
->t
= LTTV_STATE_USER_MODE
;
3425 es
= process
->state
= &g_array_index(process
->execution_stack
,
3426 LttvExecutionState
, 1);
3427 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
3428 es
->s
= LTTV_STATE_UNNAMED
;
3429 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3433 /* The process has already been created :
3434 * Probably was forked while dumping the process state or
3435 * was simply scheduled in prior to get the state dump event.
3437 process
->ppid
= parent_pid
;
3438 process
->tgid
= tgid
;
3439 process
->name
= g_quark_from_string(command
);
3440 process
->type
= type
;
3442 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3444 if(es
->t
== LTTV_STATE_MODE_UNKNOWN
) {
3445 if(type
== LTTV_STATE_KERNEL_THREAD
)
3446 es
->t
= LTTV_STATE_SYSCALL
;
3448 es
->t
= LTTV_STATE_USER_MODE
;
3451 /* Don't mess around with the stack, it will eventually become
3452 * ok after the end of state dump. */
3459 gint
lttv_state_hook_add_event_hooks(void *hook_data
, void *call_data
)
3461 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
3463 lttv_state_add_event_hooks(tss
);
3468 void lttv_state_add_event_hooks(LttvTracesetState
*self
)
3470 LttvTraceset
*traceset
= self
->parent
.ts
;
3472 guint i
, j
, k
, nb_trace
, nb_tracefile
;
3476 LttvTracefileState
*tfs
;
3482 LttvAttributeValue val
;
3484 nb_trace
= lttv_traceset_number(traceset
);
3485 for(i
= 0 ; i
< nb_trace
; i
++) {
3486 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
3488 /* Find the eventtype id for the following events and register the
3489 associated by id hooks. */
3491 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 20);
3492 //hooks = g_array_set_size(hooks, 19); // Max possible number of hooks.
3495 lttv_trace_find_hook(ts
->parent
.t
,
3497 LTT_EVENT_SYSCALL_ENTRY
,
3498 FIELD_ARRAY(LTT_FIELD_SYSCALL_ID
),
3499 syscall_entry
, NULL
, &hooks
);
3501 lttv_trace_find_hook(ts
->parent
.t
,
3503 LTT_EVENT_SYSCALL_EXIT
,
3505 syscall_exit
, NULL
, &hooks
);
3507 lttv_trace_find_hook(ts
->parent
.t
,
3509 LTT_EVENT_TRAP_ENTRY
,
3510 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
3511 trap_entry
, NULL
, &hooks
);
3513 lttv_trace_find_hook(ts
->parent
.t
,
3515 LTT_EVENT_TRAP_EXIT
,
3517 trap_exit
, NULL
, &hooks
);
3519 lttv_trace_find_hook(ts
->parent
.t
,
3521 LTT_EVENT_PAGE_FAULT_ENTRY
,
3522 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
3523 trap_entry
, NULL
, &hooks
);
3525 lttv_trace_find_hook(ts
->parent
.t
,
3527 LTT_EVENT_PAGE_FAULT_EXIT
,
3529 trap_exit
, NULL
, &hooks
);
3531 lttv_trace_find_hook(ts
->parent
.t
,
3533 LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY
,
3534 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
3535 trap_entry
, NULL
, &hooks
);
3537 lttv_trace_find_hook(ts
->parent
.t
,
3539 LTT_EVENT_PAGE_FAULT_NOSEM_EXIT
,
3541 trap_exit
, NULL
, &hooks
);
3543 lttv_trace_find_hook(ts
->parent
.t
,
3545 LTT_EVENT_IRQ_ENTRY
,
3546 FIELD_ARRAY(LTT_FIELD_IRQ_ID
),
3547 irq_entry
, NULL
, &hooks
);
3549 lttv_trace_find_hook(ts
->parent
.t
,
3553 irq_exit
, NULL
, &hooks
);
3555 lttv_trace_find_hook(ts
->parent
.t
,
3557 LTT_EVENT_SOFT_IRQ_RAISE
,
3558 FIELD_ARRAY(LTT_FIELD_SOFT_IRQ_ID
),
3559 soft_irq_raise
, NULL
, &hooks
);
3561 lttv_trace_find_hook(ts
->parent
.t
,
3563 LTT_EVENT_SOFT_IRQ_ENTRY
,
3564 FIELD_ARRAY(LTT_FIELD_SOFT_IRQ_ID
),
3565 soft_irq_entry
, NULL
, &hooks
);
3567 lttv_trace_find_hook(ts
->parent
.t
,
3569 LTT_EVENT_SOFT_IRQ_EXIT
,
3571 soft_irq_exit
, NULL
, &hooks
);
3573 lttv_trace_find_hook(ts
->parent
.t
,
3575 LTT_EVENT_SCHED_SCHEDULE
,
3576 FIELD_ARRAY(LTT_FIELD_PREV_PID
, LTT_FIELD_NEXT_PID
,
3577 LTT_FIELD_PREV_STATE
),
3578 schedchange
, NULL
, &hooks
);
3580 lttv_trace_find_hook(ts
->parent
.t
,
3582 LTT_EVENT_PROCESS_FORK
,
3583 FIELD_ARRAY(LTT_FIELD_PARENT_PID
, LTT_FIELD_CHILD_PID
,
3584 LTT_FIELD_CHILD_TGID
),
3585 process_fork
, NULL
, &hooks
);
3587 lttv_trace_find_hook(ts
->parent
.t
,
3589 LTT_EVENT_KTHREAD_CREATE
,
3590 FIELD_ARRAY(LTT_FIELD_PID
),
3591 process_kernel_thread
, NULL
, &hooks
);
3593 lttv_trace_find_hook(ts
->parent
.t
,
3595 LTT_EVENT_PROCESS_EXIT
,
3596 FIELD_ARRAY(LTT_FIELD_PID
),
3597 process_exit
, NULL
, &hooks
);
3599 lttv_trace_find_hook(ts
->parent
.t
,
3601 LTT_EVENT_PROCESS_FREE
,
3602 FIELD_ARRAY(LTT_FIELD_PID
),
3603 process_free
, NULL
, &hooks
);
3605 lttv_trace_find_hook(ts
->parent
.t
,
3608 FIELD_ARRAY(LTT_FIELD_FILENAME
),
3609 process_exec
, NULL
, &hooks
);
3611 lttv_trace_find_hook(ts
->parent
.t
,
3612 LTT_CHANNEL_USERSPACE
,
3613 LTT_EVENT_THREAD_BRAND
,
3614 FIELD_ARRAY(LTT_FIELD_NAME
),
3615 thread_brand
, NULL
, &hooks
);
3617 /* statedump-related hooks */
3618 lttv_trace_find_hook(ts
->parent
.t
,
3619 LTT_CHANNEL_TASK_STATE
,
3620 LTT_EVENT_PROCESS_STATE
,
3621 FIELD_ARRAY(LTT_FIELD_PID
, LTT_FIELD_PARENT_PID
, LTT_FIELD_NAME
,
3622 LTT_FIELD_TYPE
, LTT_FIELD_MODE
, LTT_FIELD_SUBMODE
,
3623 LTT_FIELD_STATUS
, LTT_FIELD_TGID
),
3624 enum_process_state
, NULL
, &hooks
);
3626 lttv_trace_find_hook(ts
->parent
.t
,
3627 LTT_CHANNEL_GLOBAL_STATE
,
3628 LTT_EVENT_STATEDUMP_END
,
3630 statedump_end
, NULL
, &hooks
);
3632 lttv_trace_find_hook(ts
->parent
.t
,
3633 LTT_CHANNEL_IRQ_STATE
,
3634 LTT_EVENT_LIST_INTERRUPT
,
3635 FIELD_ARRAY(LTT_FIELD_ACTION
, LTT_FIELD_IRQ_ID
),
3636 enum_interrupt
, NULL
, &hooks
);
3638 lttv_trace_find_hook(ts
->parent
.t
,
3640 LTT_EVENT_REQUEST_ISSUE
,
3641 FIELD_ARRAY(LTT_FIELD_MAJOR
, LTT_FIELD_MINOR
, LTT_FIELD_OPERATION
),
3642 bdev_request_issue
, NULL
, &hooks
);
3644 lttv_trace_find_hook(ts
->parent
.t
,
3646 LTT_EVENT_REQUEST_COMPLETE
,
3647 FIELD_ARRAY(LTT_FIELD_MAJOR
, LTT_FIELD_MINOR
, LTT_FIELD_OPERATION
),
3648 bdev_request_complete
, NULL
, &hooks
);
3650 lttv_trace_find_hook(ts
->parent
.t
,
3651 LTT_CHANNEL_USERSPACE
,
3652 LTT_EVENT_FUNCTION_ENTRY
,
3653 FIELD_ARRAY(LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
),
3654 function_entry
, NULL
, &hooks
);
3656 lttv_trace_find_hook(ts
->parent
.t
,
3657 LTT_CHANNEL_USERSPACE
,
3658 LTT_EVENT_FUNCTION_EXIT
,
3659 FIELD_ARRAY(LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
),
3660 function_exit
, NULL
, &hooks
);
3662 lttv_trace_find_hook(ts
->parent
.t
,
3663 LTT_CHANNEL_SYSCALL_STATE
,
3664 LTT_EVENT_SYS_CALL_TABLE
,
3665 FIELD_ARRAY(LTT_FIELD_ID
, LTT_FIELD_ADDRESS
, LTT_FIELD_SYMBOL
),
3666 dump_syscall
, NULL
, &hooks
);
3668 lttv_trace_find_hook(ts
->parent
.t
,
3669 LTT_CHANNEL_KPROBE_STATE
,
3670 LTT_EVENT_KPROBE_TABLE
,
3671 FIELD_ARRAY(LTT_FIELD_IP
, LTT_FIELD_SYMBOL
),
3672 dump_kprobe
, NULL
, &hooks
);
3674 lttv_trace_find_hook(ts
->parent
.t
,
3675 LTT_CHANNEL_SOFTIRQ_STATE
,
3676 LTT_EVENT_SOFTIRQ_VEC
,
3677 FIELD_ARRAY(LTT_FIELD_ID
, LTT_FIELD_ADDRESS
, LTT_FIELD_SYMBOL
),
3678 dump_softirq
, NULL
, &hooks
);
3680 /* Add these hooks to each event_by_id hooks list */
3682 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3684 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3686 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
3687 LttvTracefileContext
*, j
));
3689 for(k
= 0 ; k
< hooks
->len
; k
++) {
3690 th
= &g_array_index(hooks
, LttvTraceHook
, k
);
3691 if (th
->mdata
== tfs
->parent
.tf
->mdata
)
3693 lttv_hooks_by_id_find(tfs
->parent
.event_by_id
, th
->id
),
3699 lttv_attribute_find(ts
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
3700 *(val
.v_pointer
) = hooks
;
3704 gint
lttv_state_hook_remove_event_hooks(void *hook_data
, void *call_data
)
3706 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
3708 lttv_state_remove_event_hooks(tss
);
3713 void lttv_state_remove_event_hooks(LttvTracesetState
*self
)
3715 LttvTraceset
*traceset
= self
->parent
.ts
;
3717 guint i
, j
, k
, nb_trace
, nb_tracefile
;
3721 LttvTracefileState
*tfs
;
3727 LttvAttributeValue val
;
3729 nb_trace
= lttv_traceset_number(traceset
);
3730 for(i
= 0 ; i
< nb_trace
; i
++) {
3731 ts
= LTTV_TRACE_STATE(self
->parent
.traces
[i
]);
3733 lttv_attribute_find(ts
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
3734 hooks
= *(val
.v_pointer
);
3736 /* Remove these hooks from each event_by_id hooks list */
3738 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3740 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3742 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
3743 LttvTracefileContext
*, j
));
3745 for(k
= 0 ; k
< hooks
->len
; k
++) {
3746 th
= &g_array_index(hooks
, LttvTraceHook
, k
);
3747 if (th
->mdata
== tfs
->parent
.tf
->mdata
)
3748 lttv_hooks_remove_data(
3749 lttv_hooks_by_id_find(tfs
->parent
.event_by_id
, th
->id
),
3754 lttv_trace_hook_remove_all(&hooks
);
3755 g_array_free(hooks
, TRUE
);
3759 static gboolean
state_save_event_hook(void *hook_data
, void *call_data
)
3761 guint
*event_count
= (guint
*)hook_data
;
3763 /* Only save at LTTV_STATE_SAVE_INTERVAL */
3764 if(likely((*event_count
)++ < LTTV_STATE_SAVE_INTERVAL
))
3769 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3771 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3773 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
3775 LttvAttributeValue value
;
3777 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
3778 LTTV_STATE_SAVED_STATES
);
3779 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
3780 value
= lttv_attribute_add(saved_states_tree
,
3781 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
3782 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
3783 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
3784 *(value
.v_time
) = self
->parent
.timestamp
;
3785 lttv_state_save(tcs
, saved_state_tree
);
3786 g_debug("Saving state at time %lu.%lu", self
->parent
.timestamp
.tv_sec
,
3787 self
->parent
.timestamp
.tv_nsec
);
3789 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
3794 static gboolean
state_save_after_trace_hook(void *hook_data
, void *call_data
)
3796 LttvTraceState
*tcs
= (LttvTraceState
*)(call_data
);
3798 *(tcs
->max_time_state_recomputed_in_seek
) = tcs
->parent
.time_span
.end_time
;
3803 guint
lttv_state_current_cpu(LttvTracefileState
*tfs
)
3811 static gboolean
block_start(void *hook_data
, void *call_data
)
3813 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3815 LttvTracefileState
*tfcs
;
3817 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3819 LttEventPosition
*ep
;
3821 guint i
, nb_block
, nb_event
, nb_tracefile
;
3825 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
3827 LttvAttributeValue value
;
3829 ep
= ltt_event_position_new();
3831 nb_tracefile
= tcs
->parent
.tracefiles
->len
;
3833 /* Count the number of events added since the last block end in any
3836 for(i
= 0 ; i
< nb_tracefile
; i
++) {
3838 LTTV_TRACEFILE_STATE(&g_array_index(tcs
->parent
.tracefiles
,
3839 LttvTracefileContext
, i
));
3840 ltt_event_position(tfcs
->parent
.e
, ep
);
3841 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
3842 tcs
->nb_event
+= nb_event
- tfcs
->saved_position
;
3843 tfcs
->saved_position
= nb_event
;
3847 if(tcs
->nb_event
>= tcs
->save_interval
) {
3848 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
3849 LTTV_STATE_SAVED_STATES
);
3850 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
3851 value
= lttv_attribute_add(saved_states_tree
,
3852 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
3853 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
3854 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
3855 *(value
.v_time
) = self
->parent
.timestamp
;
3856 lttv_state_save(tcs
, saved_state_tree
);
3858 g_debug("Saving state at time %lu.%lu", self
->parent
.timestamp
.tv_sec
,
3859 self
->parent
.timestamp
.tv_nsec
);
3861 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
3867 static gboolean
block_end(void *hook_data
, void *call_data
)
3869 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3871 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3875 LttEventPosition
*ep
;
3877 guint nb_block
, nb_event
;
3879 ep
= ltt_event_position_new();
3880 ltt_event_position(self
->parent
.e
, ep
);
3881 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
3882 tcs
->nb_event
+= nb_event
- self
->saved_position
+ 1;
3883 self
->saved_position
= 0;
3884 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
3891 void lttv_state_save_add_event_hooks(LttvTracesetState
*self
)
3893 LttvTraceset
*traceset
= self
->parent
.ts
;
3895 guint i
, j
, nb_trace
, nb_tracefile
;
3899 LttvTracefileState
*tfs
;
3901 LttvTraceHook hook_start
, hook_end
;
3903 nb_trace
= lttv_traceset_number(traceset
);
3904 for(i
= 0 ; i
< nb_trace
; i
++) {
3905 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
3907 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
3908 NULL
, NULL
, block_start
, &hook_start
);
3909 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
3910 NULL
, NULL
, block_end
, &hook_end
);
3912 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3914 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3916 LTTV_TRACEFILE_STATE(&g_array_index(ts
->parent
.tracefiles
,
3917 LttvTracefileContext
, j
));
3918 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
3919 hook_start
.id
), hook_start
.h
, NULL
, LTTV_PRIO_STATE
);
3920 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
3921 hook_end
.id
), hook_end
.h
, NULL
, LTTV_PRIO_STATE
);
3927 void lttv_state_save_add_event_hooks(LttvTracesetState
*self
)
3929 LttvTraceset
*traceset
= self
->parent
.ts
;
3931 guint i
, j
, nb_trace
, nb_tracefile
;
3935 LttvTracefileState
*tfs
;
3938 nb_trace
= lttv_traceset_number(traceset
);
3939 for(i
= 0 ; i
< nb_trace
; i
++) {
3941 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
3942 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3944 if(ts
->has_precomputed_states
) continue;
3946 guint
*event_count
= g_new(guint
, 1);
3949 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3951 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
3952 LttvTracefileContext
*, j
));
3953 lttv_hooks_add(tfs
->parent
.event
,
3954 state_save_event_hook
,
3961 lttv_process_traceset_begin(&self
->parent
,
3962 NULL
, NULL
, NULL
, NULL
, NULL
);
3966 gint
lttv_state_save_hook_add_event_hooks(void *hook_data
, void *call_data
)
3968 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
3970 lttv_state_save_add_event_hooks(tss
);
3977 void lttv_state_save_remove_event_hooks(LttvTracesetState
*self
)
3979 LttvTraceset
*traceset
= self
->parent
.ts
;
3981 guint i
, j
, nb_trace
, nb_tracefile
;
3985 LttvTracefileState
*tfs
;
3987 LttvTraceHook hook_start
, hook_end
;
3989 nb_trace
= lttv_traceset_number(traceset
);
3990 for(i
= 0 ; i
< nb_trace
; i
++) {
3991 ts
= LTTV_TRACE_STATE(self
->parent
.traces
[i
]);
3993 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
3994 NULL
, NULL
, block_start
, &hook_start
);
3996 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
3997 NULL
, NULL
, block_end
, &hook_end
);
3999 nb_tracefile
= ts
->parent
.tracefiles
->len
;
4001 for(j
= 0 ; j
< nb_tracefile
; j
++) {
4003 LTTV_TRACEFILE_STATE(&g_array_index(ts
->parent
.tracefiles
,
4004 LttvTracefileContext
, j
));
4005 lttv_hooks_remove_data(lttv_hooks_by_id_find(
4006 tfs
->parent
.event_by_id
, hook_start
.id
), hook_start
.h
, NULL
);
4007 lttv_hooks_remove_data(lttv_hooks_by_id_find(
4008 tfs
->parent
.event_by_id
, hook_end
.id
), hook_end
.h
, NULL
);
4014 void lttv_state_save_remove_event_hooks(LttvTracesetState
*self
)
4016 LttvTraceset
*traceset
= self
->parent
.ts
;
4018 guint i
, j
, nb_trace
, nb_tracefile
;
4022 LttvTracefileState
*tfs
;
4024 LttvHooks
*after_trace
= lttv_hooks_new();
4026 lttv_hooks_add(after_trace
,
4027 state_save_after_trace_hook
,
4032 lttv_process_traceset_end(&self
->parent
,
4033 NULL
, after_trace
, NULL
, NULL
, NULL
);
4035 lttv_hooks_destroy(after_trace
);
4037 nb_trace
= lttv_traceset_number(traceset
);
4038 for(i
= 0 ; i
< nb_trace
; i
++) {
4040 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
4041 nb_tracefile
= ts
->parent
.tracefiles
->len
;
4043 if(ts
->has_precomputed_states
) continue;
4045 guint
*event_count
= NULL
;
4047 for(j
= 0 ; j
< nb_tracefile
; j
++) {
4049 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
4050 LttvTracefileContext
*, j
));
4051 event_count
= lttv_hooks_remove(tfs
->parent
.event
,
4052 state_save_event_hook
);
4054 if(event_count
) g_free(event_count
);
4058 gint
lttv_state_save_hook_remove_event_hooks(void *hook_data
, void *call_data
)
4060 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
4062 lttv_state_save_remove_event_hooks(tss
);
4067 void lttv_state_traceset_seek_time_closest(LttvTracesetState
*self
, LttTime t
)
4069 LttvTraceset
*traceset
= self
->parent
.ts
;
4073 int min_pos
, mid_pos
, max_pos
;
4075 guint call_rest
= 0;
4077 LttvTraceState
*tcs
;
4079 LttvAttributeValue value
;
4081 LttvAttributeType type
;
4083 LttvAttributeName name
;
4087 LttvAttribute
*saved_states_tree
, *saved_state_tree
, *closest_tree
= NULL
;
4089 //g_tree_destroy(self->parent.pqueue);
4090 //self->parent.pqueue = g_tree_new(compare_tracefile);
4092 g_info("Entering seek_time_closest for time %lu.%lu", t
.tv_sec
, t
.tv_nsec
);
4094 nb_trace
= lttv_traceset_number(traceset
);
4095 for(i
= 0 ; i
< nb_trace
; i
++) {
4096 tcs
= (LttvTraceState
*)self
->parent
.traces
[i
];
4098 if(ltt_time_compare(t
, *(tcs
->max_time_state_recomputed_in_seek
)) < 0) {
4099 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
4100 LTTV_STATE_SAVED_STATES
);
4103 if(saved_states_tree
) {
4104 max_pos
= lttv_attribute_get_number(saved_states_tree
) - 1;
4105 mid_pos
= max_pos
/ 2;
4106 while(min_pos
< max_pos
) {
4107 type
= lttv_attribute_get(saved_states_tree
, mid_pos
, &name
, &value
,
4109 g_assert(type
== LTTV_GOBJECT
);
4110 saved_state_tree
= *((LttvAttribute
**)(value
.v_gobject
));
4111 type
= lttv_attribute_get_by_name(saved_state_tree
, LTTV_STATE_TIME
,
4113 g_assert(type
== LTTV_TIME
);
4114 if(ltt_time_compare(*(value
.v_time
), t
) < 0) {
4116 closest_tree
= saved_state_tree
;
4118 else max_pos
= mid_pos
- 1;
4120 mid_pos
= (min_pos
+ max_pos
+ 1) / 2;
4124 /* restore the closest earlier saved state */
4126 lttv_state_restore(tcs
, closest_tree
);
4130 /* There is no saved state, yet we want to have it. Restart at T0 */
4132 restore_init_state(tcs
);
4133 lttv_process_trace_seek_time(&(tcs
->parent
), ltt_time_zero
);
4136 /* We want to seek quickly without restoring/updating the state */
4138 restore_init_state(tcs
);
4139 lttv_process_trace_seek_time(&(tcs
->parent
), t
);
4142 if(!call_rest
) g_info("NOT Calling restore");
4147 traceset_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
4153 traceset_state_finalize (LttvTracesetState
*self
)
4155 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
4156 finalize(G_OBJECT(self
));
4161 traceset_state_class_init (LttvTracesetContextClass
*klass
)
4163 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
4165 gobject_class
->finalize
= (void (*)(GObject
*self
)) traceset_state_finalize
;
4166 klass
->init
= (void (*)(LttvTracesetContext
*self
, LttvTraceset
*ts
))init
;
4167 klass
->fini
= (void (*)(LttvTracesetContext
*self
))fini
;
4168 klass
->new_traceset_context
= new_traceset_context
;
4169 klass
->new_trace_context
= new_trace_context
;
4170 klass
->new_tracefile_context
= new_tracefile_context
;
4175 lttv_traceset_state_get_type(void)
4177 static GType type
= 0;
4179 static const GTypeInfo info
= {
4180 sizeof (LttvTracesetStateClass
),
4181 NULL
, /* base_init */
4182 NULL
, /* base_finalize */
4183 (GClassInitFunc
) traceset_state_class_init
, /* class_init */
4184 NULL
, /* class_finalize */
4185 NULL
, /* class_data */
4186 sizeof (LttvTracesetState
),
4187 0, /* n_preallocs */
4188 (GInstanceInitFunc
) traceset_state_instance_init
, /* instance_init */
4189 NULL
/* value handling */
4192 type
= g_type_register_static (LTTV_TRACESET_CONTEXT_TYPE
, "LttvTracesetStateType",
4200 trace_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
4206 trace_state_finalize (LttvTraceState
*self
)
4208 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_CONTEXT_TYPE
))->
4209 finalize(G_OBJECT(self
));
4214 trace_state_class_init (LttvTraceStateClass
*klass
)
4216 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
4218 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_state_finalize
;
4219 klass
->state_save
= state_save
;
4220 klass
->state_restore
= state_restore
;
4221 klass
->state_saved_free
= state_saved_free
;
4226 lttv_trace_state_get_type(void)
4228 static GType type
= 0;
4230 static const GTypeInfo info
= {
4231 sizeof (LttvTraceStateClass
),
4232 NULL
, /* base_init */
4233 NULL
, /* base_finalize */
4234 (GClassInitFunc
) trace_state_class_init
, /* class_init */
4235 NULL
, /* class_finalize */
4236 NULL
, /* class_data */
4237 sizeof (LttvTraceState
),
4238 0, /* n_preallocs */
4239 (GInstanceInitFunc
) trace_state_instance_init
, /* instance_init */
4240 NULL
/* value handling */
4243 type
= g_type_register_static (LTTV_TRACE_CONTEXT_TYPE
,
4244 "LttvTraceStateType", &info
, 0);
4251 tracefile_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
4257 tracefile_state_finalize (LttvTracefileState
*self
)
4259 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_CONTEXT_TYPE
))->
4260 finalize(G_OBJECT(self
));
4265 tracefile_state_class_init (LttvTracefileStateClass
*klass
)
4267 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
4269 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_state_finalize
;
4274 lttv_tracefile_state_get_type(void)
4276 static GType type
= 0;
4278 static const GTypeInfo info
= {
4279 sizeof (LttvTracefileStateClass
),
4280 NULL
, /* base_init */
4281 NULL
, /* base_finalize */
4282 (GClassInitFunc
) tracefile_state_class_init
, /* class_init */
4283 NULL
, /* class_finalize */
4284 NULL
, /* class_data */
4285 sizeof (LttvTracefileState
),
4286 0, /* n_preallocs */
4287 (GInstanceInitFunc
) tracefile_state_instance_init
, /* instance_init */
4288 NULL
/* value handling */
4291 type
= g_type_register_static (LTTV_TRACEFILE_CONTEXT_TYPE
,
4292 "LttvTracefileStateType", &info
, 0);
4298 static void module_init()
4300 LTTV_STATE_UNNAMED
= g_quark_from_string("");
4301 LTTV_STATE_UNBRANDED
= g_quark_from_string("");
4302 LTTV_STATE_MODE_UNKNOWN
= g_quark_from_string("MODE_UNKNOWN");
4303 LTTV_STATE_USER_MODE
= g_quark_from_string("USER_MODE");
4304 LTTV_STATE_SYSCALL
= g_quark_from_string("SYSCALL");
4305 LTTV_STATE_TRAP
= g_quark_from_string("TRAP");
4306 LTTV_STATE_IRQ
= g_quark_from_string("IRQ");
4307 LTTV_STATE_SOFT_IRQ
= g_quark_from_string("SOFTIRQ");
4308 LTTV_STATE_SUBMODE_UNKNOWN
= g_quark_from_string("UNKNOWN");
4309 LTTV_STATE_SUBMODE_NONE
= g_quark_from_string("NONE");
4310 LTTV_STATE_WAIT_FORK
= g_quark_from_string("WAIT_FORK");
4311 LTTV_STATE_WAIT_CPU
= g_quark_from_string("WAIT_CPU");
4312 LTTV_STATE_EXIT
= g_quark_from_string("EXIT");
4313 LTTV_STATE_ZOMBIE
= g_quark_from_string("ZOMBIE");
4314 LTTV_STATE_WAIT
= g_quark_from_string("WAIT");
4315 LTTV_STATE_RUN
= g_quark_from_string("RUN");
4316 LTTV_STATE_DEAD
= g_quark_from_string("DEAD");
4317 LTTV_STATE_USER_THREAD
= g_quark_from_string("USER_THREAD");
4318 LTTV_STATE_KERNEL_THREAD
= g_quark_from_string("KERNEL_THREAD");
4319 LTTV_STATE_TRACEFILES
= g_quark_from_string("tracefiles");
4320 LTTV_STATE_PROCESSES
= g_quark_from_string("processes");
4321 LTTV_STATE_PROCESS
= g_quark_from_string("process");
4322 LTTV_STATE_RUNNING_PROCESS
= g_quark_from_string("running_process");
4323 LTTV_STATE_EVENT
= g_quark_from_string("event");
4324 LTTV_STATE_SAVED_STATES
= g_quark_from_string("saved states");
4325 LTTV_STATE_SAVED_STATES_TIME
= g_quark_from_string("saved states time");
4326 LTTV_STATE_TIME
= g_quark_from_string("time");
4327 LTTV_STATE_HOOKS
= g_quark_from_string("saved state hooks");
4328 LTTV_STATE_NAME_TABLES
= g_quark_from_string("name tables");
4329 LTTV_STATE_TRACE_STATE_USE_COUNT
=
4330 g_quark_from_string("trace_state_use_count");
4331 LTTV_STATE_RESOURCE_CPUS
= g_quark_from_string("cpu resource states");
4332 LTTV_STATE_RESOURCE_CPUS
= g_quark_from_string("cpu count");
4333 LTTV_STATE_RESOURCE_IRQS
= g_quark_from_string("irq resource states");
4334 LTTV_STATE_RESOURCE_SOFT_IRQS
= g_quark_from_string("soft irq resource states");
4335 LTTV_STATE_RESOURCE_TRAPS
= g_quark_from_string("trap resource states");
4336 LTTV_STATE_RESOURCE_BLKDEVS
= g_quark_from_string("blkdevs resource states");
4338 LTT_CHANNEL_FD_STATE
= g_quark_from_string("fd_state");
4339 LTT_CHANNEL_GLOBAL_STATE
= g_quark_from_string("global_state");
4340 LTT_CHANNEL_IRQ_STATE
= g_quark_from_string("irq_state");
4341 LTT_CHANNEL_MODULE_STATE
= g_quark_from_string("module_state");
4342 LTT_CHANNEL_NETIF_STATE
= g_quark_from_string("netif_state");
4343 LTT_CHANNEL_SOFTIRQ_STATE
= g_quark_from_string("softirq_state");
4344 LTT_CHANNEL_SWAP_STATE
= g_quark_from_string("swap_state");
4345 LTT_CHANNEL_SYSCALL_STATE
= g_quark_from_string("syscall_state");
4346 LTT_CHANNEL_TASK_STATE
= g_quark_from_string("task_state");
4347 LTT_CHANNEL_VM_STATE
= g_quark_from_string("vm_state");
4348 LTT_CHANNEL_KPROBE_STATE
= g_quark_from_string("kprobe_state");
4349 LTT_CHANNEL_FS
= g_quark_from_string("fs");
4350 LTT_CHANNEL_KERNEL
= g_quark_from_string("kernel");
4351 LTT_CHANNEL_MM
= g_quark_from_string("mm");
4352 LTT_CHANNEL_USERSPACE
= g_quark_from_string("userspace");
4353 LTT_CHANNEL_BLOCK
= g_quark_from_string("block");
4355 LTT_EVENT_SYSCALL_ENTRY
= g_quark_from_string("syscall_entry");
4356 LTT_EVENT_SYSCALL_EXIT
= g_quark_from_string("syscall_exit");
4357 LTT_EVENT_TRAP_ENTRY
= g_quark_from_string("trap_entry");
4358 LTT_EVENT_TRAP_EXIT
= g_quark_from_string("trap_exit");
4359 LTT_EVENT_PAGE_FAULT_ENTRY
= g_quark_from_string("page_fault_entry");
4360 LTT_EVENT_PAGE_FAULT_EXIT
= g_quark_from_string("page_fault_exit");
4361 LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY
= g_quark_from_string("page_fault_nosem_entry");
4362 LTT_EVENT_PAGE_FAULT_NOSEM_EXIT
= g_quark_from_string("page_fault_nosem_exit");
4363 LTT_EVENT_IRQ_ENTRY
= g_quark_from_string("irq_entry");
4364 LTT_EVENT_IRQ_EXIT
= g_quark_from_string("irq_exit");
4365 LTT_EVENT_SOFT_IRQ_RAISE
= g_quark_from_string("softirq_raise");
4366 LTT_EVENT_SOFT_IRQ_ENTRY
= g_quark_from_string("softirq_entry");
4367 LTT_EVENT_SOFT_IRQ_EXIT
= g_quark_from_string("softirq_exit");
4368 LTT_EVENT_SCHED_SCHEDULE
= g_quark_from_string("sched_schedule");
4369 LTT_EVENT_PROCESS_FORK
= g_quark_from_string("process_fork");
4370 LTT_EVENT_KTHREAD_CREATE
= g_quark_from_string("kthread_create");
4371 LTT_EVENT_PROCESS_EXIT
= g_quark_from_string("process_exit");
4372 LTT_EVENT_PROCESS_FREE
= g_quark_from_string("process_free");
4373 LTT_EVENT_EXEC
= g_quark_from_string("exec");
4374 LTT_EVENT_PROCESS_STATE
= g_quark_from_string("process_state");
4375 LTT_EVENT_STATEDUMP_END
= g_quark_from_string("statedump_end");
4376 LTT_EVENT_FUNCTION_ENTRY
= g_quark_from_string("function_entry");
4377 LTT_EVENT_FUNCTION_EXIT
= g_quark_from_string("function_exit");
4378 LTT_EVENT_THREAD_BRAND
= g_quark_from_string("thread_brand");
4379 LTT_EVENT_REQUEST_ISSUE
= g_quark_from_string("_blk_request_issue");
4380 LTT_EVENT_REQUEST_COMPLETE
= g_quark_from_string("_blk_request_complete");
4381 LTT_EVENT_LIST_INTERRUPT
= g_quark_from_string("interrupt");
4382 LTT_EVENT_SYS_CALL_TABLE
= g_quark_from_string("sys_call_table");
4383 LTT_EVENT_SOFTIRQ_VEC
= g_quark_from_string("softirq_vec");
4384 LTT_EVENT_KPROBE_TABLE
= g_quark_from_string("kprobe_table");
4385 LTT_EVENT_KPROBE
= g_quark_from_string("kprobe");
4387 LTT_FIELD_SYSCALL_ID
= g_quark_from_string("syscall_id");
4388 LTT_FIELD_TRAP_ID
= g_quark_from_string("trap_id");
4389 LTT_FIELD_IRQ_ID
= g_quark_from_string("irq_id");
4390 LTT_FIELD_SOFT_IRQ_ID
= g_quark_from_string("softirq_id");
4391 LTT_FIELD_PREV_PID
= g_quark_from_string("prev_pid");
4392 LTT_FIELD_NEXT_PID
= g_quark_from_string("next_pid");
4393 LTT_FIELD_PREV_STATE
= g_quark_from_string("prev_state");
4394 LTT_FIELD_PARENT_PID
= g_quark_from_string("parent_pid");
4395 LTT_FIELD_CHILD_PID
= g_quark_from_string("child_pid");
4396 LTT_FIELD_PID
= g_quark_from_string("pid");
4397 LTT_FIELD_TGID
= g_quark_from_string("tgid");
4398 LTT_FIELD_CHILD_TGID
= g_quark_from_string("child_tgid");
4399 LTT_FIELD_FILENAME
= g_quark_from_string("filename");
4400 LTT_FIELD_NAME
= g_quark_from_string("name");
4401 LTT_FIELD_TYPE
= g_quark_from_string("type");
4402 LTT_FIELD_MODE
= g_quark_from_string("mode");
4403 LTT_FIELD_SUBMODE
= g_quark_from_string("submode");
4404 LTT_FIELD_STATUS
= g_quark_from_string("status");
4405 LTT_FIELD_THIS_FN
= g_quark_from_string("this_fn");
4406 LTT_FIELD_CALL_SITE
= g_quark_from_string("call_site");
4407 LTT_FIELD_MAJOR
= g_quark_from_string("major");
4408 LTT_FIELD_MINOR
= g_quark_from_string("minor");
4409 LTT_FIELD_OPERATION
= g_quark_from_string("direction");
4410 LTT_FIELD_ACTION
= g_quark_from_string("action");
4411 LTT_FIELD_ID
= g_quark_from_string("id");
4412 LTT_FIELD_ADDRESS
= g_quark_from_string("address");
4413 LTT_FIELD_SYMBOL
= g_quark_from_string("symbol");
4414 LTT_FIELD_IP
= g_quark_from_string("ip");
4416 LTTV_CPU_UNKNOWN
= g_quark_from_string("unknown");
4417 LTTV_CPU_IDLE
= g_quark_from_string("idle");
4418 LTTV_CPU_BUSY
= g_quark_from_string("busy");
4419 LTTV_CPU_IRQ
= g_quark_from_string("irq");
4420 LTTV_CPU_SOFT_IRQ
= g_quark_from_string("softirq");
4421 LTTV_CPU_TRAP
= g_quark_from_string("trap");
4423 LTTV_IRQ_UNKNOWN
= g_quark_from_string("unknown");
4424 LTTV_IRQ_IDLE
= g_quark_from_string("idle");
4425 LTTV_IRQ_BUSY
= g_quark_from_string("busy");
4427 LTTV_BDEV_UNKNOWN
= g_quark_from_string("unknown");
4428 LTTV_BDEV_IDLE
= g_quark_from_string("idle");
4429 LTTV_BDEV_BUSY_READING
= g_quark_from_string("busy_reading");
4430 LTTV_BDEV_BUSY_WRITING
= g_quark_from_string("busy_writing");
4433 static void module_destroy()
4438 LTTV_MODULE("state", "State computation", \
4439 "Update the system state, possibly saving it at intervals", \
4440 module_init
, module_destroy
)