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,
23 #include <lttv/lttv.h>
24 #include <lttv/module.h>
25 #include <lttv/state.h>
26 #include <ltt/facility.h>
27 #include <ltt/trace.h>
28 #include <ltt/event.h>
35 * usertrace is there only to be able to update the current CPU of the
36 * usertraces when there is a schedchange. it is a way to link the ProcessState
37 * to the associated usertrace. Link only created upon thread creation.
39 * The cpu id is necessary : it gives us back the current ProcessState when we
40 * are considering data from the usertrace.
43 #define PREALLOCATED_EXECUTION_STACK 10
45 /* Facilities Quarks */
49 LTT_FACILITY_KERNEL_ARCH
,
52 LTT_FACILITY_USER_GENERIC
,
58 LTT_EVENT_SYSCALL_ENTRY
,
59 LTT_EVENT_SYSCALL_EXIT
,
64 LTT_EVENT_SOFT_IRQ_ENTRY
,
65 LTT_EVENT_SOFT_IRQ_EXIT
,
66 LTT_EVENT_SCHED_SCHEDULE
,
67 LTT_EVENT_PROCESS_FORK
,
68 LTT_EVENT_KTHREAD_CREATE
,
69 LTT_EVENT_PROCESS_EXIT
,
70 LTT_EVENT_PROCESS_FREE
,
72 LTT_EVENT_PROCESS_STATE
,
73 LTT_EVENT_STATEDUMP_END
,
74 LTT_EVENT_FUNCTION_ENTRY
,
75 LTT_EVENT_FUNCTION_EXIT
,
76 LTT_EVENT_THREAD_BRAND
,
77 LTT_EVENT_REQUEST_ISSUE
,
78 LTT_EVENT_REQUEST_COMPLETE
;
86 LTT_FIELD_SOFT_IRQ_ID
,
108 LTTV_STATE_MODE_UNKNOWN
,
109 LTTV_STATE_USER_MODE
,
116 LTTV_STATE_SUBMODE_UNKNOWN
,
117 LTTV_STATE_SUBMODE_NONE
;
121 LTTV_STATE_WAIT_FORK
,
130 LTTV_STATE_UNBRANDED
;
133 LTTV_STATE_USER_THREAD
,
134 LTTV_STATE_KERNEL_THREAD
;
151 LTTV_BDEV_BUSY_READING
,
152 LTTV_BDEV_BUSY_WRITING
;
155 LTTV_STATE_TRACEFILES
,
156 LTTV_STATE_PROCESSES
,
158 LTTV_STATE_RUNNING_PROCESS
,
160 LTTV_STATE_SAVED_STATES
,
161 LTTV_STATE_SAVED_STATES_TIME
,
164 LTTV_STATE_NAME_TABLES
,
165 LTTV_STATE_TRACE_STATE_USE_COUNT
,
166 LTTV_STATE_RESOURCE_CPUS
,
167 LTTV_STATE_RESOURCE_IRQS
,
168 LTTV_STATE_RESOURCE_BLKDEVS
;
170 static void create_max_time(LttvTraceState
*tcs
);
172 static void get_max_time(LttvTraceState
*tcs
);
174 static void free_max_time(LttvTraceState
*tcs
);
176 static void create_name_tables(LttvTraceState
*tcs
);
178 static void get_name_tables(LttvTraceState
*tcs
);
180 static void free_name_tables(LttvTraceState
*tcs
);
182 static void free_saved_state(LttvTraceState
*tcs
);
184 static void lttv_state_free_process_table(GHashTable
*processes
);
186 static void lttv_trace_states_read_raw(LttvTraceState
*tcs
, FILE *fp
,
187 GPtrArray
*quarktable
);
189 /* Resource function prototypes */
190 static LttvBdevState
*get_hashed_bdevstate(LttvTraceState
*ts
, guint16 devcode
);
191 static LttvBdevState
*bdevstate_new(void);
192 static void bdevstate_free(LttvBdevState
*);
193 static void bdevstate_free_cb(gpointer key
, gpointer value
, gpointer user_data
);
194 static LttvBdevState
*bdevstate_copy(LttvBdevState
*bds
);
195 static LttvBdevState
*bdev_state_get(LttvTraceState
*ts
, guint16 devcode
);
198 void lttv_state_save(LttvTraceState
*self
, LttvAttribute
*container
)
200 LTTV_TRACE_STATE_GET_CLASS(self
)->state_save(self
, container
);
204 void lttv_state_restore(LttvTraceState
*self
, LttvAttribute
*container
)
206 LTTV_TRACE_STATE_GET_CLASS(self
)->state_restore(self
, container
);
210 void lttv_state_state_saved_free(LttvTraceState
*self
,
211 LttvAttribute
*container
)
213 LTTV_TRACE_STATE_GET_CLASS(self
)->state_saved_free(self
, container
);
217 guint
process_hash(gconstpointer key
)
219 guint pid
= ((const LttvProcessState
*)key
)->pid
;
220 return (pid
>>8 ^ pid
>>4 ^ pid
>>2 ^ pid
) ;
224 /* If the hash table hash function is well distributed,
225 * the process_equal should compare different pid */
226 gboolean
process_equal(gconstpointer a
, gconstpointer b
)
228 const LttvProcessState
*process_a
, *process_b
;
231 process_a
= (const LttvProcessState
*)a
;
232 process_b
= (const LttvProcessState
*)b
;
234 if(likely(process_a
->pid
!= process_b
->pid
)) ret
= FALSE
;
235 else if(likely(process_a
->pid
== 0 &&
236 process_a
->cpu
!= process_b
->cpu
)) ret
= FALSE
;
241 static void delete_usertrace(gpointer key
, gpointer value
, gpointer user_data
)
243 g_tree_destroy((GTree
*)value
);
246 static void lttv_state_free_usertraces(GHashTable
*usertraces
)
248 g_hash_table_foreach(usertraces
, delete_usertrace
, NULL
);
249 g_hash_table_destroy(usertraces
);
255 restore_init_state(LttvTraceState
*self
)
257 guint i
, nb_cpus
, nb_irqs
;
259 LttvTracefileState
*tfcs
;
261 LttTime start_time
, end_time
;
263 /* Free the process tables */
264 if(self
->processes
!= NULL
) lttv_state_free_process_table(self
->processes
);
265 if(self
->usertraces
!= NULL
) lttv_state_free_usertraces(self
->usertraces
);
266 self
->processes
= g_hash_table_new(process_hash
, process_equal
);
267 self
->usertraces
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
270 /* Seek time to beginning */
271 // Mathieu : fix : don't seek traceset here : causes inconsistency in seek
272 // closest. It's the tracecontext job to seek the trace to the beginning
273 // anyway : the init state might be used at the middle of the trace as well...
274 //g_tree_destroy(self->parent.ts_context->pqueue);
275 //self->parent.ts_context->pqueue = g_tree_new(compare_tracefile);
277 ltt_trace_time_span_get(self
->parent
.t
, &start_time
, &end_time
);
279 //lttv_process_trace_seek_time(&self->parent, ltt_time_zero);
281 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
282 nb_irqs
= self
->nb_irqs
;
284 /* Put the per cpu running_process to beginning state : process 0. */
285 for(i
=0; i
< nb_cpus
; i
++) {
286 LttvExecutionState
*es
;
287 self
->running_process
[i
] = lttv_state_create_process(self
, NULL
, i
, 0, 0,
288 LTTV_STATE_UNNAMED
, &start_time
);
289 /* We are not sure is it's a kernel thread or normal thread, put the
290 * bottom stack state to unknown */
291 self
->running_process
[i
]->execution_stack
=
292 g_array_set_size(self
->running_process
[i
]->execution_stack
, 1);
293 es
= self
->running_process
[i
]->state
=
294 &g_array_index(self
->running_process
[i
]->execution_stack
,
295 LttvExecutionState
, 0);
296 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
297 es
->s
= LTTV_STATE_UNNAMED
;
299 //self->running_process[i]->state->s = LTTV_STATE_RUN;
300 self
->running_process
[i
]->cpu
= i
;
302 /* reset cpu states */
303 if(self
->cpu_states
[i
].mode_stack
->len
> 0)
304 g_array_remove_range(self
->cpu_states
[i
].mode_stack
, 0, self
->cpu_states
[i
].mode_stack
->len
);
307 /* reset irq states */
308 for(i
=0; i
<nb_irqs
; i
++) {
309 if(self
->irq_states
[i
].mode_stack
->len
> 0)
310 g_array_remove_range(self
->irq_states
[i
].mode_stack
, 0, self
->irq_states
[i
].mode_stack
->len
);
313 /* reset bdev states */
314 g_hash_table_foreach(self
->bdev_states
, bdevstate_free_cb
, NULL
);
315 g_hash_table_steal_all(self
->bdev_states
);
318 nb_tracefile
= self
->parent
.tracefiles
->len
;
320 for(i
= 0 ; i
< nb_tracefile
; i
++) {
322 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
323 LttvTracefileContext
*, i
));
324 ltt_trace_time_span_get(self
->parent
.t
, &tfcs
->parent
.timestamp
, NULL
);
325 // tfcs->saved_position = 0;
326 tfcs
->process
= lttv_state_create_process(tfcs
, NULL
,0);
327 tfcs
->process
->state
->s
= LTTV_STATE_RUN
;
328 tfcs
->process
->last_cpu
= tfcs
->cpu_name
;
329 tfcs
->process
->last_cpu_index
= ltt_tracefile_num(((LttvTracefileContext
*)tfcs
)->tf
);
334 //static LttTime time_zero = {0,0};
336 static gint
compare_usertraces(gconstpointer a
, gconstpointer b
,
339 const LttTime
*t1
= (const LttTime
*)a
;
340 const LttTime
*t2
= (const LttTime
*)b
;
342 return ltt_time_compare(*t1
, *t2
);
345 static void free_usertrace_key(gpointer data
)
350 #define MAX_STRING_LEN 4096
353 state_load_saved_states(LttvTraceState
*tcs
)
356 GPtrArray
*quarktable
;
361 tcs
->has_precomputed_states
= FALSE
;
365 gchar buf
[MAX_STRING_LEN
];
368 trace_path
= g_quark_to_string(ltt_trace_name(tcs
->parent
.t
));
369 strncpy(path
, trace_path
, PATH_MAX
-1);
370 count
= strnlen(trace_path
, PATH_MAX
-1);
371 // quarktable : open, test
372 strncat(path
, "/precomputed/quarktable", PATH_MAX
-count
-1);
373 fp
= fopen(path
, "r");
375 quarktable
= g_ptr_array_sized_new(4096);
377 /* Index 0 is null */
379 if(hdr
== EOF
) return;
380 g_assert(hdr
== HDR_QUARKS
);
384 if(hdr
== EOF
) break;
385 g_assert(hdr
== HDR_QUARK
);
386 g_ptr_array_set_size(quarktable
, q
+1);
389 fread(&buf
[i
], sizeof(gchar
), 1, fp
);
390 if(buf
[i
] == '\0' || feof(fp
)) break;
393 len
= strnlen(buf
, MAX_STRING_LEN
-1);
394 g_ptr_array_index (quarktable
, q
) = g_new(gchar
, len
+1);
395 strncpy(g_ptr_array_index (quarktable
, q
), buf
, len
+1);
401 // saved_states : open, test
402 strncpy(path
, trace_path
, PATH_MAX
-1);
403 count
= strnlen(trace_path
, PATH_MAX
-1);
404 strncat(path
, "/precomputed/states", PATH_MAX
-count
-1);
405 fp
= fopen(path
, "r");
409 if(hdr
!= HDR_TRACE
) goto end
;
411 lttv_trace_states_read_raw(tcs
, fp
, quarktable
);
413 tcs
->has_precomputed_states
= TRUE
;
418 /* Free the quarktable */
419 for(i
=0; i
<quarktable
->len
; i
++) {
420 string
= g_ptr_array_index (quarktable
, i
);
423 g_ptr_array_free(quarktable
, TRUE
);
428 init(LttvTracesetState
*self
, LttvTraceset
*ts
)
430 guint i
, j
, nb_trace
, nb_tracefile
, nb_cpu
;
433 LttvTraceContext
*tc
;
437 LttvTracefileState
*tfcs
;
439 LttvAttributeValue v
;
441 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
442 init((LttvTracesetContext
*)self
, ts
);
444 nb_trace
= lttv_traceset_number(ts
);
445 for(i
= 0 ; i
< nb_trace
; i
++) {
446 tc
= self
->parent
.traces
[i
];
447 tcs
= LTTV_TRACE_STATE(tc
);
448 tcs
->save_interval
= LTTV_STATE_SAVE_INTERVAL
;
449 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_TRACE_STATE_USE_COUNT
,
453 if(*(v
.v_uint
) == 1) {
454 create_name_tables(tcs
);
455 create_max_time(tcs
);
457 get_name_tables(tcs
);
460 nb_tracefile
= tc
->tracefiles
->len
;
461 nb_cpu
= ltt_trace_get_num_cpu(tc
->t
);
462 nb_irq
= tcs
->nb_irqs
;
463 tcs
->processes
= NULL
;
464 tcs
->usertraces
= NULL
;
465 tcs
->running_process
= g_new(LttvProcessState
*, nb_cpu
);
467 /* init cpu resource stuff */
468 tcs
->cpu_states
= g_new(LttvCPUState
, nb_cpu
);
469 for(j
= 0; j
<nb_cpu
; j
++) {
470 tcs
->cpu_states
[j
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvCPUMode
));
471 g_assert(tcs
->cpu_states
[j
].mode_stack
!= NULL
);
474 /* init irq resource stuff */
475 tcs
->irq_states
= g_new(LttvIRQState
, nb_irq
);
476 for(j
= 0; j
<nb_irq
; j
++) {
477 tcs
->irq_states
[j
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvIRQMode
));
478 g_assert(tcs
->irq_states
[j
].mode_stack
!= NULL
);
481 /* init bdev resource stuff */
482 tcs
->bdev_states
= g_hash_table_new(g_int_hash
, g_int_equal
);
484 restore_init_state(tcs
);
485 for(j
= 0 ; j
< nb_tracefile
; j
++) {
487 LTTV_TRACEFILE_STATE(g_array_index(tc
->tracefiles
,
488 LttvTracefileContext
*, j
));
489 tfcs
->tracefile_name
= ltt_tracefile_name(tfcs
->parent
.tf
);
490 tfcs
->cpu
= ltt_tracefile_cpu(tfcs
->parent
.tf
);
491 tfcs
->cpu_state
= &(tcs
->cpu_states
[tfcs
->cpu
]);
492 if(ltt_tracefile_tid(tfcs
->parent
.tf
) != 0) {
493 /* It's a Usertrace */
494 guint tid
= ltt_tracefile_tid(tfcs
->parent
.tf
);
495 GTree
*usertrace_tree
= (GTree
*)g_hash_table_lookup(tcs
->usertraces
,
497 if(!usertrace_tree
) {
498 usertrace_tree
= g_tree_new_full(compare_usertraces
,
499 NULL
, free_usertrace_key
, NULL
);
500 g_hash_table_insert(tcs
->usertraces
,
501 (gpointer
)tid
, usertrace_tree
);
503 LttTime
*timestamp
= g_new(LttTime
, 1);
504 *timestamp
= ltt_interpolate_time_from_tsc(tfcs
->parent
.tf
,
505 ltt_tracefile_creation(tfcs
->parent
.tf
));
506 g_tree_insert(usertrace_tree
, timestamp
, tfcs
);
510 /* See if the trace has saved states */
511 state_load_saved_states(tcs
);
516 fini(LttvTracesetState
*self
)
522 LttvTracefileState
*tfcs
;
524 LttvAttributeValue v
;
526 nb_trace
= lttv_traceset_number(LTTV_TRACESET_CONTEXT(self
)->ts
);
527 for(i
= 0 ; i
< nb_trace
; i
++) {
528 tcs
= (LttvTraceState
*)(LTTV_TRACESET_CONTEXT(self
)->traces
[i
]);
529 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_TRACE_STATE_USE_COUNT
,
532 g_assert(*(v
.v_uint
) != 0);
535 if(*(v
.v_uint
) == 0) {
536 free_name_tables(tcs
);
538 free_saved_state(tcs
);
540 g_free(tcs
->running_process
);
541 tcs
->running_process
= NULL
;
542 lttv_state_free_process_table(tcs
->processes
);
543 lttv_state_free_usertraces(tcs
->usertraces
);
544 tcs
->processes
= NULL
;
545 tcs
->usertraces
= NULL
;
547 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
548 fini((LttvTracesetContext
*)self
);
552 static LttvTracesetContext
*
553 new_traceset_context(LttvTracesetContext
*self
)
555 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATE_TYPE
, NULL
));
559 static LttvTraceContext
*
560 new_trace_context(LttvTracesetContext
*self
)
562 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATE_TYPE
, NULL
));
566 static LttvTracefileContext
*
567 new_tracefile_context(LttvTracesetContext
*self
)
569 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATE_TYPE
, NULL
));
573 /* Write the process state of the trace */
575 static void write_process_state(gpointer key
, gpointer value
,
578 LttvProcessState
*process
;
580 LttvExecutionState
*es
;
582 FILE *fp
= (FILE *)user_data
;
587 process
= (LttvProcessState
*)value
;
589 " <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\">\n",
590 process
, process
->pid
, process
->tgid
, process
->ppid
,
591 g_quark_to_string(process
->type
),
592 process
->creation_time
.tv_sec
,
593 process
->creation_time
.tv_nsec
,
594 process
->insertion_time
.tv_sec
,
595 process
->insertion_time
.tv_nsec
,
596 g_quark_to_string(process
->name
),
597 g_quark_to_string(process
->brand
),
600 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
601 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
602 fprintf(fp
, " <ES MODE=\"%s\" SUBMODE=\"%s\" ENTRY_S=%lu ENTRY_NS=%lu",
603 g_quark_to_string(es
->t
), g_quark_to_string(es
->n
),
604 es
->entry
.tv_sec
, es
->entry
.tv_nsec
);
605 fprintf(fp
, " CHANGE_S=%lu CHANGE_NS=%lu STATUS=\"%s\"/>\n",
606 es
->change
.tv_sec
, es
->change
.tv_nsec
, g_quark_to_string(es
->s
));
609 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
610 address
= &g_array_index(process
->user_stack
, guint64
, i
);
611 fprintf(fp
, " <USER_STACK ADDRESS=\"%llu\"/>\n",
615 if(process
->usertrace
) {
616 fprintf(fp
, " <USERTRACE NAME=\"%s\" CPU=%u\n/>",
617 g_quark_to_string(process
->usertrace
->tracefile_name
),
618 process
->usertrace
->cpu
);
622 fprintf(fp
, " </PROCESS>\n");
626 void lttv_state_write(LttvTraceState
*self
, LttTime t
, FILE *fp
)
628 guint i
, nb_tracefile
, nb_block
, offset
;
631 LttvTracefileState
*tfcs
;
635 LttEventPosition
*ep
;
639 ep
= ltt_event_position_new();
641 fprintf(fp
,"<PROCESS_STATE TIME_S=%lu TIME_NS=%lu>\n", t
.tv_sec
, t
.tv_nsec
);
643 g_hash_table_foreach(self
->processes
, write_process_state
, fp
);
645 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
646 for(i
=0;i
<nb_cpus
;i
++) {
647 fprintf(fp
," <CPU NUM=%u RUNNING_PROCESS=%u>\n",
648 i
, self
->running_process
[i
]->pid
);
651 nb_tracefile
= self
->parent
.tracefiles
->len
;
653 for(i
= 0 ; i
< nb_tracefile
; i
++) {
655 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
656 LttvTracefileContext
*, i
));
657 fprintf(fp
, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
658 tfcs
->parent
.timestamp
.tv_sec
,
659 tfcs
->parent
.timestamp
.tv_nsec
);
660 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
661 if(e
== NULL
) fprintf(fp
,"/>\n");
663 ltt_event_position(e
, ep
);
664 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
665 fprintf(fp
, " BLOCK=%u OFFSET=%u TSC=%llu/>\n", nb_block
, offset
,
670 fprintf(fp
,"</PROCESS_STATE>\n");
674 static void write_process_state_raw(gpointer key
, gpointer value
,
677 LttvProcessState
*process
;
679 LttvExecutionState
*es
;
681 FILE *fp
= (FILE *)user_data
;
686 process
= (LttvProcessState
*)value
;
687 fputc(HDR_PROCESS
, fp
);
688 //fwrite(&header, sizeof(header), 1, fp);
689 //fprintf(fp, "%s", g_quark_to_string(process->type));
691 fwrite(&process
->type
, sizeof(process
->type
), 1, fp
);
692 //fprintf(fp, "%s", g_quark_to_string(process->name));
694 fwrite(&process
->name
, sizeof(process
->name
), 1, fp
);
695 //fprintf(fp, "%s", g_quark_to_string(process->brand));
697 fwrite(&process
->brand
, sizeof(process
->brand
), 1, fp
);
698 fwrite(&process
->pid
, sizeof(process
->pid
), 1, fp
);
699 fwrite(&process
->tgid
, sizeof(process
->tgid
), 1, fp
);
700 fwrite(&process
->ppid
, sizeof(process
->ppid
), 1, fp
);
701 fwrite(&process
->cpu
, sizeof(process
->cpu
), 1, fp
);
702 fwrite(&process
->creation_time
, sizeof(process
->creation_time
), 1, fp
);
703 fwrite(&process
->insertion_time
, sizeof(process
->insertion_time
), 1, fp
);
707 " <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",
708 process
, process
->pid
, process
->tgid
, process
->ppid
,
709 g_quark_to_string(process
->type
),
710 process
->creation_time
.tv_sec
,
711 process
->creation_time
.tv_nsec
,
712 process
->insertion_time
.tv_sec
,
713 process
->insertion_time
.tv_nsec
,
714 g_quark_to_string(process
->name
),
715 g_quark_to_string(process
->brand
),
719 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
720 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
723 //fprintf(fp, "%s", g_quark_to_string(es->t));
725 fwrite(&es
->t
, sizeof(es
->t
), 1, fp
);
726 //fprintf(fp, "%s", g_quark_to_string(es->n));
728 fwrite(&es
->n
, sizeof(es
->n
), 1, fp
);
729 //fprintf(fp, "%s", g_quark_to_string(es->s));
731 fwrite(&es
->s
, sizeof(es
->s
), 1, fp
);
732 fwrite(&es
->entry
, sizeof(es
->entry
), 1, fp
);
733 fwrite(&es
->change
, sizeof(es
->change
), 1, fp
);
734 fwrite(&es
->cum_cpu_time
, sizeof(es
->cum_cpu_time
), 1, fp
);
736 fprintf(fp
, " <ES MODE=\"%s\" SUBMODE=\"%s\" ENTRY_S=%lu ENTRY_NS=%lu",
737 g_quark_to_string(es
->t
), g_quark_to_string(es
->n
),
738 es
->entry
.tv_sec
, es
->entry
.tv_nsec
);
739 fprintf(fp
, " CHANGE_S=%lu CHANGE_NS=%lu STATUS=\"%s\"/>\n",
740 es
->change
.tv_sec
, es
->change
.tv_nsec
, g_quark_to_string(es
->s
));
744 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
745 address
= &g_array_index(process
->user_stack
, guint64
, i
);
746 fputc(HDR_USER_STACK
, fp
);
747 fwrite(&address
, sizeof(address
), 1, fp
);
749 fprintf(fp
, " <USER_STACK ADDRESS=\"%llu\"/>\n",
754 if(process
->usertrace
) {
755 fputc(HDR_USERTRACE
, fp
);
756 //fprintf(fp, "%s", g_quark_to_string(process->usertrace->tracefile_name));
758 fwrite(&process
->usertrace
->tracefile_name
,
759 sizeof(process
->usertrace
->tracefile_name
), 1, fp
);
760 fwrite(&process
->usertrace
->cpu
, sizeof(process
->usertrace
->cpu
), 1, fp
);
762 fprintf(fp
, " <USERTRACE NAME=\"%s\" CPU=%u\n/>",
763 g_quark_to_string(process
->usertrace
->tracefile_name
),
764 process
->usertrace
->cpu
);
771 void lttv_state_write_raw(LttvTraceState
*self
, LttTime t
, FILE *fp
)
773 guint i
, nb_tracefile
, nb_block
, offset
;
776 LttvTracefileState
*tfcs
;
780 LttEventPosition
*ep
;
784 ep
= ltt_event_position_new();
786 //fprintf(fp,"<PROCESS_STATE TIME_S=%lu TIME_NS=%lu>\n", t.tv_sec, t.tv_nsec);
787 fputc(HDR_PROCESS_STATE
, fp
);
788 fwrite(&t
, sizeof(t
), 1, fp
);
790 g_hash_table_foreach(self
->processes
, write_process_state_raw
, fp
);
792 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
793 for(i
=0;i
<nb_cpus
;i
++) {
795 fwrite(&i
, sizeof(i
), 1, fp
); /* cpu number */
796 fwrite(&self
->running_process
[i
]->pid
,
797 sizeof(self
->running_process
[i
]->pid
), 1, fp
);
798 //fprintf(fp," <CPU NUM=%u RUNNING_PROCESS=%u>\n",
799 // i, self->running_process[i]->pid);
802 nb_tracefile
= self
->parent
.tracefiles
->len
;
804 for(i
= 0 ; i
< nb_tracefile
; i
++) {
806 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
807 LttvTracefileContext
*, i
));
808 // fprintf(fp, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
809 // tfcs->parent.timestamp.tv_sec,
810 // tfcs->parent.timestamp.tv_nsec);
811 fputc(HDR_TRACEFILE
, fp
);
812 fwrite(&tfcs
->parent
.timestamp
, sizeof(tfcs
->parent
.timestamp
), 1, fp
);
813 /* Note : if timestamp if LTT_TIME_INFINITE, there will be no
814 * position following : end of trace */
815 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
817 ltt_event_position(e
, ep
);
818 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
819 //fprintf(fp, " BLOCK=%u OFFSET=%u TSC=%llu/>\n", nb_block, offset,
821 fwrite(&nb_block
, sizeof(nb_block
), 1, fp
);
822 fwrite(&offset
, sizeof(offset
), 1, fp
);
823 fwrite(&tsc
, sizeof(tsc
), 1, fp
);
830 /* Read process state from a file */
832 /* Called because a HDR_PROCESS was found */
833 static void read_process_state_raw(LttvTraceState
*self
, FILE *fp
,
834 GPtrArray
*quarktable
)
836 LttvExecutionState
*es
;
837 LttvProcessState
*process
, *parent_process
;
838 LttvProcessState tmp
;
845 /* TODO : check return value */
846 fread(&tmp
.type
, sizeof(tmp
.type
), 1, fp
);
847 fread(&tmp
.name
, sizeof(tmp
.name
), 1, fp
);
848 fread(&tmp
.brand
, sizeof(tmp
.brand
), 1, fp
);
849 fread(&tmp
.pid
, sizeof(tmp
.pid
), 1, fp
);
850 fread(&tmp
.tgid
, sizeof(tmp
.tgid
), 1, fp
);
851 fread(&tmp
.ppid
, sizeof(tmp
.ppid
), 1, fp
);
852 fread(&tmp
.cpu
, sizeof(tmp
.cpu
), 1, fp
);
853 fread(&tmp
.creation_time
, sizeof(tmp
.creation_time
), 1, fp
);
854 fread(&tmp
.insertion_time
, sizeof(tmp
.insertion_time
), 1, fp
);
857 process
= lttv_state_find_process(self
, tmp
.cpu
, tmp
.pid
);
859 /* We must link to the parent */
860 parent_process
= lttv_state_find_process_or_create(self
, ANY_CPU
, tmp
.ppid
,
862 process
= lttv_state_find_process(self
, ANY_CPU
, tmp
.pid
);
863 if(process
== NULL
) {
864 process
= lttv_state_create_process(self
, parent_process
, tmp
.cpu
,
866 g_quark_from_string((gchar
*)g_ptr_array_index(quarktable
, tmp
.name
)),
870 process
->insertion_time
= tmp
.insertion_time
;
871 process
->creation_time
= tmp
.creation_time
;
872 process
->type
= g_quark_from_string(
873 (gchar
*)g_ptr_array_index(quarktable
, tmp
.type
));
874 process
->tgid
= tmp
.tgid
;
875 process
->ppid
= tmp
.ppid
;
876 process
->brand
= g_quark_from_string(
877 (gchar
*)g_ptr_array_index(quarktable
, tmp
.brand
));
879 g_quark_from_string((gchar
*)g_ptr_array_index(quarktable
, tmp
.name
));
883 if(feof(fp
) || ferror(fp
)) goto end_loop
;
885 gint hdr
= fgetc(fp
);
886 if(hdr
== EOF
) goto end_loop
;
890 process
->execution_stack
=
891 g_array_set_size(process
->execution_stack
,
892 process
->execution_stack
->len
+ 1);
893 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
894 process
->execution_stack
->len
-1);
897 fread(&es
->t
, sizeof(es
->t
), 1, fp
);
898 es
->t
= g_quark_from_string(
899 (gchar
*)g_ptr_array_index(quarktable
, es
->t
));
900 fread(&es
->n
, sizeof(es
->n
), 1, fp
);
901 es
->n
= g_quark_from_string(
902 (gchar
*)g_ptr_array_index(quarktable
, es
->n
));
903 fread(&es
->s
, sizeof(es
->s
), 1, fp
);
904 es
->s
= g_quark_from_string(
905 (gchar
*)g_ptr_array_index(quarktable
, es
->s
));
906 fread(&es
->entry
, sizeof(es
->entry
), 1, fp
);
907 fread(&es
->change
, sizeof(es
->change
), 1, fp
);
908 fread(&es
->cum_cpu_time
, sizeof(es
->cum_cpu_time
), 1, fp
);
911 process
->user_stack
= g_array_set_size(process
->user_stack
,
912 process
->user_stack
->len
+ 1);
913 address
= &g_array_index(process
->user_stack
, guint64
,
914 process
->user_stack
->len
-1);
915 fread(address
, sizeof(address
), 1, fp
);
916 process
->current_function
= *address
;
919 fread(&tmpq
, sizeof(tmpq
), 1, fp
);
920 fread(&process
->usertrace
->cpu
, sizeof(process
->usertrace
->cpu
), 1, fp
);
932 /* Called because a HDR_PROCESS_STATE was found */
933 /* Append a saved state to the trace states */
934 void lttv_state_read_raw(LttvTraceState
*self
, FILE *fp
, GPtrArray
*quarktable
)
936 guint i
, nb_tracefile
, nb_block
, offset
;
938 LttvTracefileState
*tfcs
;
940 LttEventPosition
*ep
;
948 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
950 LttvAttributeValue value
;
951 GTree
*pqueue
= self
->parent
.ts_context
->pqueue
;
952 ep
= ltt_event_position_new();
954 restore_init_state(self
);
956 fread(&t
, sizeof(t
), 1, fp
);
959 if(feof(fp
) || ferror(fp
)) goto end_loop
;
961 if(hdr
== EOF
) goto end_loop
;
965 /* Call read_process_state_raw */
966 read_process_state_raw(self
, fp
, quarktable
);
976 case HDR_PROCESS_STATE
:
982 g_error("Error while parsing saved state file : unknown data header %d",
988 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
989 for(i
=0;i
<nb_cpus
;i
++) {
992 g_assert(hdr
== HDR_CPU
);
993 fread(&cpu_num
, sizeof(cpu_num
), 1, fp
); /* cpu number */
994 g_assert(i
== cpu_num
);
995 fread(&self
->running_process
[i
]->pid
,
996 sizeof(self
->running_process
[i
]->pid
), 1, fp
);
999 nb_tracefile
= self
->parent
.tracefiles
->len
;
1001 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1003 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1004 LttvTracefileContext
*, i
));
1005 // fprintf(fp, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
1006 // tfcs->parent.timestamp.tv_sec,
1007 // tfcs->parent.timestamp.tv_nsec);
1008 g_tree_remove(pqueue
, &tfcs
->parent
);
1010 g_assert(hdr
== HDR_TRACEFILE
);
1011 fread(&tfcs
->parent
.timestamp
, sizeof(tfcs
->parent
.timestamp
), 1, fp
);
1012 /* Note : if timestamp if LTT_TIME_INFINITE, there will be no
1013 * position following : end of trace */
1014 if(ltt_time_compare(tfcs
->parent
.timestamp
, ltt_time_infinite
) != 0) {
1015 fread(&nb_block
, sizeof(nb_block
), 1, fp
);
1016 fread(&offset
, sizeof(offset
), 1, fp
);
1017 fread(&tsc
, sizeof(tsc
), 1, fp
);
1018 ltt_event_position_set(ep
, tfcs
->parent
.tf
, nb_block
, offset
, tsc
);
1019 gint ret
= ltt_tracefile_seek_position(tfcs
->parent
.tf
, ep
);
1021 g_tree_insert(pqueue
, &tfcs
->parent
, &tfcs
->parent
);
1026 saved_states_tree
= lttv_attribute_find_subdir(self
->parent
.t_a
,
1027 LTTV_STATE_SAVED_STATES
);
1028 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1029 value
= lttv_attribute_add(saved_states_tree
,
1030 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
1031 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
1032 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
1033 *(value
.v_time
) = t
;
1034 lttv_state_save(self
, saved_state_tree
);
1035 g_debug("Saving state at time %lu.%lu", t
.tv_sec
,
1038 *(self
->max_time_state_recomputed_in_seek
) = t
;
1042 /* Called when a HDR_TRACE is found */
1043 void lttv_trace_states_read_raw(LttvTraceState
*tcs
, FILE *fp
,
1044 GPtrArray
*quarktable
)
1049 if(feof(fp
) || ferror(fp
)) goto end_loop
;
1051 if(hdr
== EOF
) goto end_loop
;
1054 case HDR_PROCESS_STATE
:
1055 /* Call read_process_state_raw */
1056 lttv_state_read_raw(tcs
, fp
, quarktable
);
1064 case HDR_USER_STACK
:
1068 g_error("Error while parsing saved state file :"
1069 " unexpected data header %d",
1073 g_error("Error while parsing saved state file : unknown data header %d",
1078 *(tcs
->max_time_state_recomputed_in_seek
) = tcs
->parent
.time_span
.end_time
;
1079 restore_init_state(tcs
);
1080 lttv_process_trace_seek_time(tcs
, ltt_time_zero
);
1086 /* Copy each process from an existing hash table to a new one */
1088 static void copy_process_state(gpointer key
, gpointer value
,gpointer user_data
)
1090 LttvProcessState
*process
, *new_process
;
1092 GHashTable
*new_processes
= (GHashTable
*)user_data
;
1096 process
= (LttvProcessState
*)value
;
1097 new_process
= g_new(LttvProcessState
, 1);
1098 *new_process
= *process
;
1099 new_process
->execution_stack
= g_array_sized_new(FALSE
, FALSE
,
1100 sizeof(LttvExecutionState
), PREALLOCATED_EXECUTION_STACK
);
1101 new_process
->execution_stack
=
1102 g_array_set_size(new_process
->execution_stack
,
1103 process
->execution_stack
->len
);
1104 for(i
= 0 ; i
< process
->execution_stack
->len
; i
++) {
1105 g_array_index(new_process
->execution_stack
, LttvExecutionState
, i
) =
1106 g_array_index(process
->execution_stack
, LttvExecutionState
, i
);
1108 new_process
->state
= &g_array_index(new_process
->execution_stack
,
1109 LttvExecutionState
, new_process
->execution_stack
->len
- 1);
1110 new_process
->user_stack
= g_array_sized_new(FALSE
, FALSE
,
1111 sizeof(guint64
), 0);
1112 new_process
->user_stack
=
1113 g_array_set_size(new_process
->user_stack
,
1114 process
->user_stack
->len
);
1115 for(i
= 0 ; i
< process
->user_stack
->len
; i
++) {
1116 g_array_index(new_process
->user_stack
, guint64
, i
) =
1117 g_array_index(process
->user_stack
, guint64
, i
);
1119 new_process
->current_function
= process
->current_function
;
1120 g_hash_table_insert(new_processes
, new_process
, new_process
);
1124 static GHashTable
*lttv_state_copy_process_table(GHashTable
*processes
)
1126 GHashTable
*new_processes
= g_hash_table_new(process_hash
, process_equal
);
1128 g_hash_table_foreach(processes
, copy_process_state
, new_processes
);
1129 return new_processes
;
1132 static LttvCPUState
*lttv_state_copy_cpu_states(LttvCPUState
*states
, guint n
)
1135 LttvCPUState
*retval
;
1137 retval
= g_malloc(n
*sizeof(LttvCPUState
));
1139 for(i
=0; i
<n
; i
++) {
1140 retval
[i
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvCPUMode
));
1141 retval
[i
].last_irq
= states
[i
].last_irq
;
1142 g_array_set_size(retval
[i
].mode_stack
, states
[i
].mode_stack
->len
);
1143 for(j
=0; j
<states
[i
].mode_stack
->len
; j
++) {
1144 g_array_index(retval
[i
].mode_stack
, GQuark
, j
) = g_array_index(states
[i
].mode_stack
, GQuark
, j
);
1151 static void lttv_state_free_cpu_states(LttvCPUState
*states
, guint n
)
1155 for(i
=0; i
<n
; i
++) {
1156 g_array_free(states
[i
].mode_stack
, FALSE
);
1162 static LttvIRQState
*lttv_state_copy_irq_states(LttvIRQState
*states
, guint n
)
1165 LttvIRQState
*retval
;
1167 retval
= g_malloc(n
*sizeof(LttvIRQState
));
1169 for(i
=0; i
<n
; i
++) {
1170 retval
[i
].mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(LttvIRQMode
));
1171 g_array_set_size(retval
[i
].mode_stack
, states
[i
].mode_stack
->len
);
1172 for(j
=0; j
<states
[i
].mode_stack
->len
; j
++) {
1173 g_array_index(retval
[i
].mode_stack
, GQuark
, j
) = g_array_index(states
[i
].mode_stack
, GQuark
, j
);
1180 static void lttv_state_free_irq_states(LttvIRQState
*states
, guint n
)
1184 for(i
=0; i
<n
; i
++) {
1185 g_array_free(states
[i
].mode_stack
, FALSE
);
1191 /* bdevstate stuff */
1193 static LttvBdevState
*get_hashed_bdevstate(LttvTraceState
*ts
, guint16 devcode
)
1195 gint devcode_gint
= devcode
;
1196 gpointer bdev
= g_hash_table_lookup(ts
->bdev_states
, &devcode_gint
);
1198 LttvBdevState
*bdevstate
= g_malloc(sizeof(LttvBdevState
));
1199 bdevstate
->mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(GQuark
));
1201 gint
* key
= g_malloc(sizeof(gint
));
1203 g_hash_table_insert(ts
->bdev_states
, key
, bdevstate
);
1211 static LttvBdevState
*bdevstate_new(void)
1213 LttvBdevState
*retval
;
1214 retval
= g_malloc(sizeof(LttvBdevState
));
1215 retval
->mode_stack
= g_array_new(FALSE
, FALSE
, sizeof(GQuark
));
1220 static void bdevstate_free(LttvBdevState
*bds
)
1222 g_array_free(bds
->mode_stack
, FALSE
);
1226 static void bdevstate_free_cb(gpointer key
, gpointer value
, gpointer user_data
)
1228 LttvBdevState
*bds
= (LttvBdevState
*) value
;
1230 bdevstate_free(bds
);
1233 static LttvBdevState
*bdevstate_copy(LttvBdevState
*bds
)
1235 LttvBdevState
*retval
;
1237 retval
= bdevstate_new();
1238 g_array_insert_vals(retval
->mode_stack
, 0, bds
->mode_stack
->data
, bds
->mode_stack
->len
);
1243 static void insert_and_copy_bdev_state(gpointer k
, gpointer v
, gpointer u
)
1245 GHashTable
*ht
= (GHashTable
*)u
;
1246 LttvBdevState
*bds
= (LttvBdevState
*)v
;
1247 LttvBdevState
*newbds
;
1249 newbds
= bdevstate_copy(v
);
1251 g_hash_table_insert(u
, k
, newbds
);
1254 static GHashTable
*lttv_state_copy_blkdev_hashtable(GHashTable
*ht
)
1258 retval
= g_hash_table_new(g_int_hash
, g_int_equal
);
1260 g_hash_table_foreach(ht
, insert_and_copy_bdev_state
, retval
);
1265 /* Free a hashtable and the LttvBdevState structures its values
1268 static void lttv_state_free_blkdev_hashtable(GHashTable
*ht
)
1270 g_hash_table_foreach(ht
, bdevstate_free_cb
, NULL
);
1271 g_hash_table_destroy(ht
);
1274 /* The saved state for each trace contains a member "processes", which
1275 stores a copy of the process table, and a member "tracefiles" with
1276 one entry per tracefile. Each tracefile has a "process" member pointing
1277 to the current process and a "position" member storing the tracefile
1278 position (needed to seek to the current "next" event. */
1280 static void state_save(LttvTraceState
*self
, LttvAttribute
*container
)
1282 guint i
, nb_tracefile
, nb_cpus
, nb_irqs
;
1284 LttvTracefileState
*tfcs
;
1286 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
1288 guint
*running_process
;
1290 LttvAttributeType type
;
1292 LttvAttributeValue value
;
1294 LttvAttributeName name
;
1296 LttEventPosition
*ep
;
1298 tracefiles_tree
= lttv_attribute_find_subdir(container
,
1299 LTTV_STATE_TRACEFILES
);
1301 value
= lttv_attribute_add(container
, LTTV_STATE_PROCESSES
,
1303 *(value
.v_pointer
) = lttv_state_copy_process_table(self
->processes
);
1305 /* Add the currently running processes array */
1306 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
1307 running_process
= g_new(guint
, nb_cpus
);
1308 for(i
=0;i
<nb_cpus
;i
++) {
1309 running_process
[i
] = self
->running_process
[i
]->pid
;
1311 value
= lttv_attribute_add(container
, LTTV_STATE_RUNNING_PROCESS
,
1313 *(value
.v_pointer
) = running_process
;
1315 g_info("State save");
1317 nb_tracefile
= self
->parent
.tracefiles
->len
;
1319 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1321 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1322 LttvTracefileContext
*, i
));
1323 tracefile_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1324 value
= lttv_attribute_add(tracefiles_tree
, i
,
1326 *(value
.v_gobject
) = (GObject
*)tracefile_tree
;
1328 value
= lttv_attribute_add(tracefile_tree
, LTTV_STATE_PROCESS
,
1330 *(value
.v_uint
) = tfcs
->process
->pid
;
1332 value
= lttv_attribute_add(tracefile_tree
, LTTV_STATE_EVENT
,
1334 /* Only save the position if the tfs has not infinite time. */
1335 //if(!g_tree_lookup(self->parent.ts_context->pqueue, &tfcs->parent)
1336 // && current_tfcs != tfcs) {
1337 if(ltt_time_compare(tfcs
->parent
.timestamp
, ltt_time_infinite
) == 0) {
1338 *(value
.v_pointer
) = NULL
;
1340 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
1341 ep
= ltt_event_position_new();
1342 ltt_event_position(e
, ep
);
1343 *(value
.v_pointer
) = ep
;
1345 guint nb_block
, offset
;
1348 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
1349 g_info("Block %u offset %u tsc %llu time %lu.%lu", nb_block
, offset
,
1351 tfcs
->parent
.timestamp
.tv_sec
, tfcs
->parent
.timestamp
.tv_nsec
);
1355 /* save the cpu state */
1357 guint size
= sizeof(LttvCPUState
)*nb_cpus
;
1358 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_CPUS
,
1360 *(value
.v_pointer
) = lttv_state_copy_cpu_states(self
->cpu_states
, nb_cpus
);
1363 /* save the irq state */
1364 nb_irqs
= self
->nb_irqs
;
1366 guint size
= sizeof(LttvCPUState
)*nb_irqs
;
1367 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_IRQS
,
1369 *(value
.v_pointer
) = lttv_state_copy_irq_states(self
->irq_states
, nb_irqs
);
1372 /* save the blkdev states */
1373 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_BLKDEVS
,
1375 *(value
.v_pointer
) = lttv_state_copy_blkdev_hashtable(self
->bdev_states
);
1379 static void state_restore(LttvTraceState
*self
, LttvAttribute
*container
)
1381 guint i
, nb_tracefile
, pid
, nb_cpus
, nb_irqs
;
1383 LttvTracefileState
*tfcs
;
1385 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
1387 guint
*running_process
;
1389 LttvAttributeType type
;
1391 LttvAttributeValue value
;
1393 LttvAttributeName name
;
1397 LttEventPosition
*ep
;
1399 LttvTracesetContext
*tsc
= self
->parent
.ts_context
;
1401 tracefiles_tree
= lttv_attribute_find_subdir(container
,
1402 LTTV_STATE_TRACEFILES
);
1404 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_PROCESSES
,
1406 g_assert(type
== LTTV_POINTER
);
1407 lttv_state_free_process_table(self
->processes
);
1408 self
->processes
= lttv_state_copy_process_table(*(value
.v_pointer
));
1410 /* Add the currently running processes array */
1411 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
1412 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RUNNING_PROCESS
,
1414 g_assert(type
== LTTV_POINTER
);
1415 running_process
= *(value
.v_pointer
);
1416 for(i
=0;i
<nb_cpus
;i
++) {
1417 pid
= running_process
[i
];
1418 self
->running_process
[i
] = lttv_state_find_process(self
, i
, pid
);
1419 g_assert(self
->running_process
[i
] != NULL
);
1422 nb_tracefile
= self
->parent
.tracefiles
->len
;
1424 //g_tree_destroy(tsc->pqueue);
1425 //tsc->pqueue = g_tree_new(compare_tracefile);
1427 /* restore cpu resource states */
1428 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS
, &value
);
1429 g_assert(type
== LTTV_POINTER
);
1430 lttv_state_free_cpu_states(self
->cpu_states
, nb_cpus
);
1431 self
->cpu_states
= lttv_state_copy_cpu_states(*(value
.v_pointer
), nb_cpus
);
1433 /* restore irq resource states */
1434 nb_irqs
= self
->nb_irqs
;
1435 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_IRQS
, &value
);
1436 g_assert(type
== LTTV_POINTER
);
1437 lttv_state_free_irq_states(self
->irq_states
, nb_irqs
);
1438 self
->irq_states
= lttv_state_copy_irq_states(*(value
.v_pointer
), nb_irqs
);
1440 /* restore the blkdev states */
1441 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_BLKDEVS
, &value
);
1442 g_assert(type
== LTTV_POINTER
);
1443 lttv_state_free_blkdev_hashtable(self
->bdev_states
);
1444 self
->bdev_states
= lttv_state_copy_blkdev_hashtable(*(value
.v_pointer
));
1446 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1448 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1449 LttvTracefileContext
*, i
));
1450 type
= lttv_attribute_get(tracefiles_tree
, i
, &name
, &value
, &is_named
);
1451 g_assert(type
== LTTV_GOBJECT
);
1452 tracefile_tree
= *((LttvAttribute
**)(value
.v_gobject
));
1454 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_PROCESS
,
1456 g_assert(type
== LTTV_UINT
);
1457 pid
= *(value
.v_uint
);
1458 tfcs
->process
= lttv_state_find_process_or_create(tfcs
, pid
);
1460 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_EVENT
,
1462 g_assert(type
== LTTV_POINTER
);
1463 //g_assert(*(value.v_pointer) != NULL);
1464 ep
= *(value
.v_pointer
);
1465 g_assert(tfcs
->parent
.t_context
!= NULL
);
1467 tfcs
->cpu_state
= &self
->cpu_states
[tfcs
->cpu
];
1469 LttvTracefileContext
*tfc
= LTTV_TRACEFILE_CONTEXT(tfcs
);
1470 g_tree_remove(tsc
->pqueue
, tfc
);
1473 g_assert(ltt_tracefile_seek_position(tfc
->tf
, ep
) == 0);
1474 tfc
->timestamp
= ltt_event_time(ltt_tracefile_get_event(tfc
->tf
));
1475 g_assert(ltt_time_compare(tfc
->timestamp
, ltt_time_infinite
) != 0);
1476 g_tree_insert(tsc
->pqueue
, tfc
, tfc
);
1477 g_info("Restoring state for a tf at time %lu.%lu", tfc
->timestamp
.tv_sec
, tfc
->timestamp
.tv_nsec
);
1479 tfc
->timestamp
= ltt_time_infinite
;
1485 static void state_saved_free(LttvTraceState
*self
, LttvAttribute
*container
)
1487 guint i
, nb_tracefile
, nb_cpus
;
1489 LttvTracefileState
*tfcs
;
1491 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
1493 guint
*running_process
;
1495 LttvAttributeType type
;
1497 LttvAttributeValue value
;
1499 LttvAttributeName name
;
1503 LttEventPosition
*ep
;
1505 tracefiles_tree
= lttv_attribute_find_subdir(container
,
1506 LTTV_STATE_TRACEFILES
);
1507 g_object_ref(G_OBJECT(tracefiles_tree
));
1508 lttv_attribute_remove_by_name(container
, LTTV_STATE_TRACEFILES
);
1510 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_PROCESSES
,
1512 g_assert(type
== LTTV_POINTER
);
1513 lttv_state_free_process_table(*(value
.v_pointer
));
1514 *(value
.v_pointer
) = NULL
;
1515 lttv_attribute_remove_by_name(container
, LTTV_STATE_PROCESSES
);
1517 /* Free running processes array */
1518 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
1519 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RUNNING_PROCESS
,
1521 g_assert(type
== LTTV_POINTER
);
1522 running_process
= *(value
.v_pointer
);
1523 g_free(running_process
);
1525 nb_tracefile
= self
->parent
.tracefiles
->len
;
1527 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1529 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1530 LttvTracefileContext
*, i
));
1531 type
= lttv_attribute_get(tracefiles_tree
, i
, &name
, &value
, &is_named
);
1532 g_assert(type
== LTTV_GOBJECT
);
1533 tracefile_tree
= *((LttvAttribute
**)(value
.v_gobject
));
1535 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_EVENT
,
1537 g_assert(type
== LTTV_POINTER
);
1538 if(*(value
.v_pointer
) != NULL
) g_free(*(value
.v_pointer
));
1540 g_object_unref(G_OBJECT(tracefiles_tree
));
1544 static void free_saved_state(LttvTraceState
*self
)
1548 LttvAttributeType type
;
1550 LttvAttributeValue value
;
1552 LttvAttributeName name
;
1556 LttvAttribute
*saved_states
;
1558 saved_states
= lttv_attribute_find_subdir(self
->parent
.t_a
,
1559 LTTV_STATE_SAVED_STATES
);
1561 nb
= lttv_attribute_get_number(saved_states
);
1562 for(i
= 0 ; i
< nb
; i
++) {
1563 type
= lttv_attribute_get(saved_states
, i
, &name
, &value
, &is_named
);
1564 g_assert(type
== LTTV_GOBJECT
);
1565 state_saved_free(self
, *((LttvAttribute
**)value
.v_gobject
));
1568 lttv_attribute_remove_by_name(self
->parent
.t_a
, LTTV_STATE_SAVED_STATES
);
1573 create_max_time(LttvTraceState
*tcs
)
1575 LttvAttributeValue v
;
1577 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
1579 g_assert(*(v
.v_pointer
) == NULL
);
1580 *(v
.v_pointer
) = g_new(LttTime
,1);
1581 *((LttTime
*)*(v
.v_pointer
)) = ltt_time_zero
;
1586 get_max_time(LttvTraceState
*tcs
)
1588 LttvAttributeValue v
;
1590 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
1592 g_assert(*(v
.v_pointer
) != NULL
);
1593 tcs
->max_time_state_recomputed_in_seek
= (LttTime
*)*(v
.v_pointer
);
1598 free_max_time(LttvTraceState
*tcs
)
1600 LttvAttributeValue v
;
1602 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
1604 g_free(*(v
.v_pointer
));
1605 *(v
.v_pointer
) = NULL
;
1609 typedef struct _LttvNameTables
{
1610 // FIXME GQuark *eventtype_names;
1611 GQuark
*syscall_names
;
1617 GQuark
*soft_irq_names
;
1623 create_name_tables(LttvTraceState
*tcs
)
1627 GQuark f_name
, e_name
;
1631 LttvTraceHookByFacility
*thf
;
1637 GString
*fe_name
= g_string_new("");
1639 LttvNameTables
*name_tables
= g_new(LttvNameTables
, 1);
1641 LttvAttributeValue v
;
1643 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_NAME_TABLES
,
1645 g_assert(*(v
.v_pointer
) == NULL
);
1646 *(v
.v_pointer
) = name_tables
;
1647 #if 0 // Use iteration over the facilities_by_name and then list all event
1648 // types of each facility
1649 nb
= ltt_trace_eventtype_number(tcs
->parent
.t
);
1650 name_tables
->eventtype_names
= g_new(GQuark
, nb
);
1651 for(i
= 0 ; i
< nb
; i
++) {
1652 et
= ltt_trace_eventtype_get(tcs
->parent
.t
, i
);
1653 e_name
= ltt_eventtype_name(et
);
1654 f_name
= ltt_facility_name(ltt_eventtype_facility(et
));
1655 g_string_printf(fe_name
, "%s.%s", f_name
, e_name
);
1656 name_tables
->eventtype_names
[i
] = g_quark_from_string(fe_name
->str
);
1659 if(!lttv_trace_find_hook(tcs
->parent
.t
,
1660 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_SYSCALL_ENTRY
,
1661 LTT_FIELD_SYSCALL_ID
, 0, 0,
1664 thf
= lttv_trace_hook_get_first(&h
);
1666 t
= ltt_field_type(thf
->f1
);
1667 nb
= ltt_type_element_number(t
);
1669 lttv_trace_hook_destroy(&h
);
1671 name_tables
->syscall_names
= g_new(GQuark
, nb
);
1672 name_tables
->nb_syscalls
= nb
;
1674 for(i
= 0 ; i
< nb
; i
++) {
1675 name_tables
->syscall_names
[i
] = ltt_enum_string_get(t
, i
);
1676 if(!name_tables
->syscall_names
[i
]) {
1677 GString
*string
= g_string_new("");
1678 g_string_printf(string
, "syscall %u", i
);
1679 name_tables
->syscall_names
[i
] = g_quark_from_string(string
->str
);
1680 g_string_free(string
, TRUE
);
1684 //name_tables->syscall_names = g_new(GQuark, 256);
1685 //for(i = 0 ; i < 256 ; i++) {
1686 // g_string_printf(fe_name, "syscall %d", i);
1687 // name_tables->syscall_names[i] = g_quark_from_string(fe_name->str);
1690 name_tables
->syscall_names
= NULL
;
1691 name_tables
->nb_syscalls
= 0;
1694 if(!lttv_trace_find_hook(tcs
->parent
.t
, LTT_FACILITY_KERNEL_ARCH
,
1695 LTT_EVENT_TRAP_ENTRY
,
1696 LTT_FIELD_TRAP_ID
, 0, 0,
1699 thf
= lttv_trace_hook_get_first(&h
);
1701 t
= ltt_field_type(thf
->f1
);
1702 //nb = ltt_type_element_number(t);
1704 lttv_trace_hook_destroy(&h
);
1707 name_tables->trap_names = g_new(GQuark, nb);
1708 for(i = 0 ; i < nb ; i++) {
1709 name_tables->trap_names[i] = g_quark_from_string(
1710 ltt_enum_string_get(t, i));
1713 name_tables
->nb_traps
= 256;
1714 name_tables
->trap_names
= g_new(GQuark
, 256);
1715 for(i
= 0 ; i
< 256 ; i
++) {
1716 g_string_printf(fe_name
, "trap %d", i
);
1717 name_tables
->trap_names
[i
] = g_quark_from_string(fe_name
->str
);
1720 name_tables
->trap_names
= NULL
;
1721 name_tables
->nb_traps
= 0;
1724 if(!lttv_trace_find_hook(tcs
->parent
.t
,
1725 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_ENTRY
,
1726 LTT_FIELD_IRQ_ID
, 0, 0,
1729 thf
= lttv_trace_hook_get_first(&h
);
1731 t
= ltt_field_type(thf
->f1
);
1732 //nb = ltt_type_element_number(t);
1734 lttv_trace_hook_destroy(&h
);
1737 name_tables->irq_names = g_new(GQuark, nb);
1738 for(i = 0 ; i < nb ; i++) {
1739 name_tables->irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
1743 name_tables
->nb_irqs
= 256;
1744 name_tables
->irq_names
= g_new(GQuark
, 256);
1745 for(i
= 0 ; i
< 256 ; i
++) {
1746 g_string_printf(fe_name
, "irq %d", i
);
1747 name_tables
->irq_names
[i
] = g_quark_from_string(fe_name
->str
);
1750 name_tables
->nb_irqs
= 0;
1751 name_tables
->irq_names
= NULL
;
1754 name_tables->soft_irq_names = g_new(GQuark, nb);
1755 for(i = 0 ; i < nb ; i++) {
1756 name_tables->soft_irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
1760 name_tables
->nb_softirqs
= 256;
1761 name_tables
->soft_irq_names
= g_new(GQuark
, 256);
1762 for(i
= 0 ; i
< 256 ; i
++) {
1763 g_string_printf(fe_name
, "softirq %d", i
);
1764 name_tables
->soft_irq_names
[i
] = g_quark_from_string(fe_name
->str
);
1768 g_string_free(fe_name
, TRUE
);
1773 get_name_tables(LttvTraceState
*tcs
)
1775 LttvNameTables
*name_tables
;
1777 LttvAttributeValue v
;
1779 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_NAME_TABLES
,
1781 g_assert(*(v
.v_pointer
) != NULL
);
1782 name_tables
= (LttvNameTables
*)*(v
.v_pointer
);
1783 //tcs->eventtype_names = name_tables->eventtype_names;
1784 tcs
->syscall_names
= name_tables
->syscall_names
;
1785 tcs
->nb_syscalls
= name_tables
->nb_syscalls
;
1786 tcs
->trap_names
= name_tables
->trap_names
;
1787 tcs
->nb_traps
= name_tables
->nb_traps
;
1788 tcs
->irq_names
= name_tables
->irq_names
;
1789 tcs
->soft_irq_names
= name_tables
->soft_irq_names
;
1790 tcs
->nb_irqs
= name_tables
->nb_irqs
;
1791 tcs
->nb_softirqs
= name_tables
->nb_softirqs
;
1796 free_name_tables(LttvTraceState
*tcs
)
1798 LttvNameTables
*name_tables
;
1800 LttvAttributeValue v
;
1802 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_NAME_TABLES
,
1804 name_tables
= (LttvNameTables
*)*(v
.v_pointer
);
1805 *(v
.v_pointer
) = NULL
;
1807 // g_free(name_tables->eventtype_names);
1808 if(name_tables
->syscall_names
) g_free(name_tables
->syscall_names
);
1809 if(name_tables
->trap_names
) g_free(name_tables
->trap_names
);
1810 if(name_tables
->irq_names
) g_free(name_tables
->irq_names
);
1811 if(name_tables
->soft_irq_names
) g_free(name_tables
->soft_irq_names
);
1812 if(name_tables
) g_free(name_tables
);
1815 #ifdef HASH_TABLE_DEBUG
1817 static void test_process(gpointer key
, gpointer value
, gpointer user_data
)
1819 LttvProcessState
*process
= (LttvProcessState
*)value
;
1821 /* Test for process corruption */
1822 guint stack_len
= process
->execution_stack
->len
;
1825 static void hash_table_check(GHashTable
*table
)
1827 g_hash_table_foreach(table
, test_process
, NULL
);
1833 /* clears the stack and sets the state passed as argument */
1834 static void cpu_set_base_mode(LttvCPUState
*cpust
, LttvCPUMode state
)
1836 g_array_set_size(cpust
->mode_stack
, 1);
1837 ((GQuark
*)cpust
->mode_stack
->data
)[0] = state
;
1840 static void cpu_push_mode(LttvCPUState
*cpust
, LttvCPUMode state
)
1842 g_array_set_size(cpust
->mode_stack
, cpust
->mode_stack
->len
+ 1);
1843 ((GQuark
*)cpust
->mode_stack
->data
)[cpust
->mode_stack
->len
- 1] = state
;
1846 static void cpu_pop_mode(LttvCPUState
*cpust
)
1848 if(cpust
->mode_stack
->len
<= 1)
1849 cpu_set_base_mode(cpust
, LTTV_CPU_UNKNOWN
);
1851 g_array_set_size(cpust
->mode_stack
, cpust
->mode_stack
->len
- 1);
1854 /* clears the stack and sets the state passed as argument */
1855 static void bdev_set_base_mode(LttvBdevState
*bdevst
, LttvBdevMode state
)
1857 g_array_set_size(bdevst
->mode_stack
, 1);
1858 ((GQuark
*)bdevst
->mode_stack
->data
)[0] = state
;
1861 static void bdev_push_mode(LttvBdevState
*bdevst
, LttvBdevMode state
)
1863 g_array_set_size(bdevst
->mode_stack
, bdevst
->mode_stack
->len
+ 1);
1864 ((GQuark
*)bdevst
->mode_stack
->data
)[bdevst
->mode_stack
->len
- 1] = state
;
1867 static void bdev_pop_mode(LttvBdevState
*bdevst
)
1869 if(bdevst
->mode_stack
->len
<= 1)
1870 bdev_set_base_mode(bdevst
, LTTV_BDEV_UNKNOWN
);
1872 g_array_set_size(bdevst
->mode_stack
, bdevst
->mode_stack
->len
- 1);
1875 static void irq_set_base_mode(LttvIRQState
*irqst
, LttvIRQMode state
)
1877 g_array_set_size(irqst
->mode_stack
, 1);
1878 ((GQuark
*)irqst
->mode_stack
->data
)[0] = state
;
1881 static void irq_push_mode(LttvIRQState
*irqst
, LttvIRQMode state
)
1883 g_array_set_size(irqst
->mode_stack
, irqst
->mode_stack
->len
+ 1);
1884 ((GQuark
*)irqst
->mode_stack
->data
)[irqst
->mode_stack
->len
- 1] = state
;
1887 static void irq_pop_mode(LttvIRQState
*irqst
)
1889 if(irqst
->mode_stack
->len
<= 1)
1890 irq_set_base_mode(irqst
, LTTV_IRQ_UNKNOWN
);
1892 g_array_set_size(irqst
->mode_stack
, irqst
->mode_stack
->len
- 1);
1895 static void push_state(LttvTracefileState
*tfs
, LttvExecutionMode t
,
1898 LttvExecutionState
*es
;
1900 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
1901 guint cpu
= tfs
->cpu
;
1903 #ifdef HASH_TABLE_DEBUG
1904 hash_table_check(ts
->processes
);
1906 LttvProcessState
*process
= ts
->running_process
[cpu
];
1908 guint depth
= process
->execution_stack
->len
;
1910 process
->execution_stack
=
1911 g_array_set_size(process
->execution_stack
, depth
+ 1);
1914 &g_array_index(process
->execution_stack
, LttvExecutionState
, depth
- 1);
1916 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, depth
);
1919 es
->entry
= es
->change
= tfs
->parent
.timestamp
;
1920 es
->cum_cpu_time
= ltt_time_zero
;
1921 es
->s
= process
->state
->s
;
1922 process
->state
= es
;
1926 * return 1 when empty, else 0 */
1927 int lttv_state_pop_state_cleanup(LttvProcessState
*process
,
1928 LttvTracefileState
*tfs
)
1930 guint cpu
= tfs
->cpu
;
1931 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
1933 guint depth
= process
->execution_stack
->len
;
1939 process
->execution_stack
=
1940 g_array_set_size(process
->execution_stack
, depth
- 1);
1941 process
->state
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
1943 process
->state
->change
= tfs
->parent
.timestamp
;
1948 static void pop_state(LttvTracefileState
*tfs
, LttvExecutionMode t
)
1950 guint cpu
= tfs
->cpu
;
1951 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
1952 LttvProcessState
*process
= ts
->running_process
[cpu
];
1954 guint depth
= process
->execution_stack
->len
;
1956 if(process
->state
->t
!= t
){
1957 g_info("Different execution mode type (%lu.%09lu): ignore it\n",
1958 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
1959 g_info("process state has %s when pop_int is %s\n",
1960 g_quark_to_string(process
->state
->t
),
1961 g_quark_to_string(t
));
1962 g_info("{ %u, %u, %s, %s, %s }\n",
1965 g_quark_to_string(process
->name
),
1966 g_quark_to_string(process
->brand
),
1967 g_quark_to_string(process
->state
->s
));
1972 g_info("Trying to pop last state on stack (%lu.%09lu): ignore it\n",
1973 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
1977 process
->execution_stack
=
1978 g_array_set_size(process
->execution_stack
, depth
- 1);
1979 process
->state
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
1981 process
->state
->change
= tfs
->parent
.timestamp
;
1984 struct search_result
{
1985 const LttTime
*time
; /* Requested time */
1986 LttTime
*best
; /* Best result */
1989 static gint
search_usertrace(gconstpointer a
, gconstpointer b
)
1991 const LttTime
*elem_time
= (const LttTime
*)a
;
1992 /* Explicit non const cast */
1993 struct search_result
*res
= (struct search_result
*)b
;
1995 if(ltt_time_compare(*elem_time
, *(res
->time
)) < 0) {
1996 /* The usertrace was created before the schedchange */
1997 /* Get larger keys */
1999 } else if(ltt_time_compare(*elem_time
, *(res
->time
)) >= 0) {
2000 /* The usertrace was created after the schedchange time */
2001 /* Get smaller keys */
2003 if(ltt_time_compare(*elem_time
, *res
->best
) < 0) {
2004 res
->best
= elem_time
;
2007 res
->best
= elem_time
;
2014 static LttvTracefileState
*ltt_state_usertrace_find(LttvTraceState
*tcs
,
2015 guint pid
, const LttTime
*timestamp
)
2017 LttvTracefileState
*tfs
= NULL
;
2018 struct search_result res
;
2019 /* Find the usertrace associated with a pid and time interval.
2020 * Search in the usertraces by PID (within a hash) and then, for each
2021 * corresponding element of the array, find the first one with creation
2022 * timestamp the lowest, but higher or equal to "timestamp". */
2023 res
.time
= timestamp
;
2025 GTree
*usertrace_tree
= g_hash_table_lookup(tcs
->usertraces
, (gpointer
)pid
);
2026 if(usertrace_tree
) {
2027 g_tree_search(usertrace_tree
, search_usertrace
, &res
);
2029 tfs
= g_tree_lookup(usertrace_tree
, res
.best
);
2037 lttv_state_create_process(LttvTraceState
*tcs
, LttvProcessState
*parent
,
2038 guint cpu
, guint pid
, guint tgid
, GQuark name
, const LttTime
*timestamp
)
2040 LttvProcessState
*process
= g_new(LttvProcessState
, 1);
2042 LttvExecutionState
*es
;
2044 LttvTraceContext
*tc
= (LttvTraceContext
*)tcs
;
2049 process
->tgid
= tgid
;
2051 process
->name
= name
;
2052 process
->brand
= LTTV_STATE_UNBRANDED
;
2053 //process->last_cpu = tfs->cpu_name;
2054 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
2055 process
->type
= LTTV_STATE_USER_THREAD
;
2056 process
->usertrace
= ltt_state_usertrace_find(tcs
, pid
, timestamp
);
2057 process
->current_function
= 0; //function 0x0 by default.
2059 g_info("Process %u, core %p", process
->pid
, process
);
2060 g_hash_table_insert(tcs
->processes
, process
, process
);
2063 process
->ppid
= parent
->pid
;
2064 process
->creation_time
= *timestamp
;
2067 /* No parent. This process exists but we are missing all information about
2068 its creation. The birth time is set to zero but we remember the time of
2073 process
->creation_time
= ltt_time_zero
;
2076 process
->insertion_time
= *timestamp
;
2077 sprintf(buffer
,"%d-%lu.%lu",pid
, process
->creation_time
.tv_sec
,
2078 process
->creation_time
.tv_nsec
);
2079 process
->pid_time
= g_quark_from_string(buffer
);
2081 //process->last_cpu = tfs->cpu_name;
2082 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
2083 process
->execution_stack
= g_array_sized_new(FALSE
, FALSE
,
2084 sizeof(LttvExecutionState
), PREALLOCATED_EXECUTION_STACK
);
2085 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 2);
2086 es
= process
->state
= &g_array_index(process
->execution_stack
,
2087 LttvExecutionState
, 0);
2088 es
->t
= LTTV_STATE_USER_MODE
;
2089 es
->n
= LTTV_STATE_SUBMODE_NONE
;
2090 es
->entry
= *timestamp
;
2091 //g_assert(timestamp->tv_sec != 0);
2092 es
->change
= *timestamp
;
2093 es
->cum_cpu_time
= ltt_time_zero
;
2094 es
->s
= LTTV_STATE_RUN
;
2096 es
= process
->state
= &g_array_index(process
->execution_stack
,
2097 LttvExecutionState
, 1);
2098 es
->t
= LTTV_STATE_SYSCALL
;
2099 es
->n
= LTTV_STATE_SUBMODE_NONE
;
2100 es
->entry
= *timestamp
;
2101 //g_assert(timestamp->tv_sec != 0);
2102 es
->change
= *timestamp
;
2103 es
->cum_cpu_time
= ltt_time_zero
;
2104 es
->s
= LTTV_STATE_WAIT_FORK
;
2106 /* Allocate an empty function call stack. If it's empty, use 0x0. */
2107 process
->user_stack
= g_array_sized_new(FALSE
, FALSE
,
2108 sizeof(guint64
), 0);
2113 LttvProcessState
*lttv_state_find_process(LttvTraceState
*ts
, guint cpu
,
2116 LttvProcessState key
;
2117 LttvProcessState
*process
;
2121 process
= g_hash_table_lookup(ts
->processes
, &key
);
2126 lttv_state_find_process_or_create(LttvTraceState
*ts
, guint cpu
, guint pid
,
2127 const LttTime
*timestamp
)
2129 LttvProcessState
*process
= lttv_state_find_process(ts
, cpu
, pid
);
2130 LttvExecutionState
*es
;
2132 /* Put ltt_time_zero creation time for unexisting processes */
2133 if(unlikely(process
== NULL
)) {
2134 process
= lttv_state_create_process(ts
,
2135 NULL
, cpu
, pid
, 0, LTTV_STATE_UNNAMED
, timestamp
);
2136 /* We are not sure is it's a kernel thread or normal thread, put the
2137 * bottom stack state to unknown */
2138 process
->execution_stack
=
2139 g_array_set_size(process
->execution_stack
, 1);
2140 process
->state
= es
=
2141 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
2142 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
2143 es
->s
= LTTV_STATE_UNNAMED
;
2148 /* FIXME : this function should be called when we receive an event telling that
2149 * release_task has been called in the kernel. In happens generally when
2150 * the parent waits for its child terminaison, but may also happen in special
2151 * cases in the child's exit : when the parent ignores its children SIGCCHLD or
2152 * has the flag SA_NOCLDWAIT. It can also happen when the child is part
2153 * of a killed thread ground, but isn't the leader.
2155 static void exit_process(LttvTracefileState
*tfs
, LttvProcessState
*process
)
2157 LttvTraceState
*ts
= LTTV_TRACE_STATE(tfs
->parent
.t_context
);
2158 LttvProcessState key
;
2160 key
.pid
= process
->pid
;
2161 key
.cpu
= process
->cpu
;
2162 g_hash_table_remove(ts
->processes
, &key
);
2163 g_array_free(process
->execution_stack
, TRUE
);
2164 g_array_free(process
->user_stack
, TRUE
);
2169 static void free_process_state(gpointer key
, gpointer value
,gpointer user_data
)
2171 g_array_free(((LttvProcessState
*)value
)->execution_stack
, TRUE
);
2172 g_array_free(((LttvProcessState
*)value
)->user_stack
, TRUE
);
2177 static void lttv_state_free_process_table(GHashTable
*processes
)
2179 g_hash_table_foreach(processes
, free_process_state
, NULL
);
2180 g_hash_table_destroy(processes
);
2184 static gboolean
syscall_entry(void *hook_data
, void *call_data
)
2186 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2188 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2189 LttvProcessState
*process
= ts
->running_process
[cpu
];
2190 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2191 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2192 LttField
*f
= thf
->f1
;
2194 LttvExecutionSubmode submode
;
2196 guint nb_syscalls
= ((LttvTraceState
*)(s
->parent
.t_context
))->nb_syscalls
;
2197 guint syscall
= ltt_event_get_unsigned(e
, f
);
2199 if(syscall
< nb_syscalls
) {
2200 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->syscall_names
[
2203 /* Fixup an incomplete syscall table */
2204 GString
*string
= g_string_new("");
2205 g_string_printf(string
, "syscall %u", syscall
);
2206 submode
= g_quark_from_string(string
->str
);
2207 g_string_free(string
, TRUE
);
2209 /* There can be no system call from PID 0 : unknown state */
2210 if(process
->pid
!= 0)
2211 push_state(s
, LTTV_STATE_SYSCALL
, submode
);
2216 static gboolean
syscall_exit(void *hook_data
, void *call_data
)
2218 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2220 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2221 LttvProcessState
*process
= ts
->running_process
[cpu
];
2223 /* There can be no system call from PID 0 : unknown state */
2224 if(process
->pid
!= 0)
2225 pop_state(s
, LTTV_STATE_SYSCALL
);
2230 static gboolean
trap_entry(void *hook_data
, void *call_data
)
2232 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2233 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2234 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2235 LttField
*f
= thf
->f1
;
2237 LttvExecutionSubmode submode
;
2239 guint64 nb_traps
= ((LttvTraceState
*)(s
->parent
.t_context
))->nb_traps
;
2240 guint64 trap
= ltt_event_get_long_unsigned(e
, f
);
2242 if(trap
< nb_traps
) {
2243 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->trap_names
[trap
];
2245 /* Fixup an incomplete trap table */
2246 GString
*string
= g_string_new("");
2247 g_string_printf(string
, "trap %llu", trap
);
2248 submode
= g_quark_from_string(string
->str
);
2249 g_string_free(string
, TRUE
);
2252 push_state(s
, LTTV_STATE_TRAP
, submode
);
2254 /* update cpu status */
2255 cpu_push_mode(s
->cpu_state
, LTTV_CPU_TRAP
);
2260 static gboolean
trap_exit(void *hook_data
, void *call_data
)
2262 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2264 pop_state(s
, LTTV_STATE_TRAP
);
2266 /* update cpu status */
2267 cpu_pop_mode(s
->cpu_state
);
2272 static gboolean
irq_entry(void *hook_data
, void *call_data
)
2274 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2275 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2276 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2277 guint8 fac_id
= ltt_event_facility_id(e
);
2278 guint8 ev_id
= ltt_event_eventtype_id(e
);
2279 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2280 // g_assert(lttv_trace_hook_get_first((LttvTraceHook *)hook_data)->f1 != NULL);
2281 g_assert(thf
->f1
!= NULL
);
2282 // g_assert(thf == lttv_trace_hook_get_first((LttvTraceHook *)hook_data));
2283 LttField
*f
= thf
->f1
;
2285 LttvExecutionSubmode submode
;
2286 guint64 irq
= ltt_event_get_long_unsigned(e
, f
);
2287 guint64 nb_irqs
= ((LttvTraceState
*)(s
->parent
.t_context
))->nb_irqs
;
2291 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->irq_names
[irq
];
2293 /* Fixup an incomplete irq table */
2294 GString
*string
= g_string_new("");
2295 g_string_printf(string
, "irq %llu", irq
);
2296 submode
= g_quark_from_string(string
->str
);
2297 g_string_free(string
, TRUE
);
2300 /* Do something with the info about being in user or system mode when int? */
2301 push_state(s
, LTTV_STATE_IRQ
, submode
);
2303 /* update cpu status */
2304 cpu_push_mode(s
->cpu_state
, LTTV_CPU_IRQ
);
2306 /* update irq status */
2307 s
->cpu_state
->last_irq
= irq
;
2308 irq_push_mode(&ts
->irq_states
[irq
], LTTV_IRQ_BUSY
);
2313 static gboolean
soft_irq_exit(void *hook_data
, void *call_data
)
2315 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2317 pop_state(s
, LTTV_STATE_SOFT_IRQ
);
2323 static gboolean
irq_exit(void *hook_data
, void *call_data
)
2325 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2326 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2328 pop_state(s
, LTTV_STATE_IRQ
);
2330 /* update cpu status */
2331 cpu_pop_mode(s
->cpu_state
);
2333 /* update irq status */
2334 irq_pop_mode(&ts
->irq_states
[s
->cpu_state
->last_irq
]);
2339 static gboolean
soft_irq_entry(void *hook_data
, void *call_data
)
2341 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2342 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2343 guint8 fac_id
= ltt_event_facility_id(e
);
2344 guint8 ev_id
= ltt_event_eventtype_id(e
);
2345 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2346 // g_assert(lttv_trace_hook_get_first((LttvTraceHook *)hook_data)->f1 != NULL);
2347 g_assert(thf
->f1
!= NULL
);
2348 // g_assert(thf == lttv_trace_hook_get_first((LttvTraceHook *)hook_data));
2349 LttField
*f
= thf
->f1
;
2351 LttvExecutionSubmode submode
;
2352 guint64 softirq
= ltt_event_get_long_unsigned(e
, f
);
2353 guint64 nb_softirqs
= ((LttvTraceState
*)(s
->parent
.t_context
))->nb_softirqs
;
2356 if(softirq
< nb_softirqs
) {
2357 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->soft_irq_names
[softirq
];
2359 /* Fixup an incomplete irq table */
2360 GString
*string
= g_string_new("");
2361 g_string_printf(string
, "softirq %llu", softirq
);
2362 submode
= g_quark_from_string(string
->str
);
2363 g_string_free(string
, TRUE
);
2366 /* Do something with the info about being in user or system mode when int? */
2367 push_state(s
, LTTV_STATE_SOFT_IRQ
, submode
);
2371 static gboolean
bdev_request_issue(void *hook_data
, void *call_data
)
2373 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2374 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2375 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2376 guint8 fac_id
= ltt_event_facility_id(e
);
2377 guint8 ev_id
= ltt_event_eventtype_id(e
);
2378 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2380 guint major
= ltt_event_get_long_unsigned(e
, thf
->f1
);
2381 guint minor
= ltt_event_get_long_unsigned(e
, thf
->f2
);
2382 guint oper
= ltt_event_get_long_unsigned(e
, thf
->f3
);
2383 guint16 devcode
= MKDEV(major
,minor
);
2385 /* have we seen this block device before? */
2386 gpointer bdev
= get_hashed_bdevstate(ts
, devcode
);
2389 bdev_push_mode(bdev
, LTTV_BDEV_BUSY_READING
);
2391 bdev_push_mode(bdev
, LTTV_BDEV_BUSY_WRITING
);
2396 static gboolean
bdev_request_complete(void *hook_data
, void *call_data
)
2398 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2399 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2400 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2401 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2403 guint major
= ltt_event_get_long_unsigned(e
, thf
->f1
);
2404 guint minor
= ltt_event_get_long_unsigned(e
, thf
->f2
);
2405 guint oper
= ltt_event_get_long_unsigned(e
, thf
->f3
);
2406 guint16 devcode
= MKDEV(major
,minor
);
2408 /* have we seen this block device before? */
2409 gpointer bdev
= get_hashed_bdevstate(ts
, devcode
);
2411 /* update block device */
2412 bdev_pop_mode(bdev
);
2417 static void push_function(LttvTracefileState
*tfs
, guint64 funcptr
)
2421 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
2422 guint cpu
= tfs
->cpu
;
2423 LttvProcessState
*process
= ts
->running_process
[cpu
];
2425 guint depth
= process
->user_stack
->len
;
2427 process
->user_stack
=
2428 g_array_set_size(process
->user_stack
, depth
+ 1);
2430 new_func
= &g_array_index(process
->user_stack
, guint64
, depth
);
2431 *new_func
= funcptr
;
2432 process
->current_function
= funcptr
;
2435 static void pop_function(LttvTracefileState
*tfs
, guint64 funcptr
)
2437 guint cpu
= tfs
->cpu
;
2438 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
2439 LttvProcessState
*process
= ts
->running_process
[cpu
];
2441 if(process
->current_function
!= funcptr
){
2442 g_info("Different functions (%lu.%09lu): ignore it\n",
2443 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
2444 g_info("process state has %llu when pop_function is %llu\n",
2445 process
->current_function
, funcptr
);
2446 g_info("{ %u, %u, %s, %s, %s }\n",
2449 g_quark_to_string(process
->name
),
2450 g_quark_to_string(process
->brand
),
2451 g_quark_to_string(process
->state
->s
));
2454 guint depth
= process
->user_stack
->len
;
2457 g_info("Trying to pop last function on stack (%lu.%09lu): ignore it\n",
2458 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
2462 process
->user_stack
=
2463 g_array_set_size(process
->user_stack
, depth
- 1);
2464 process
->current_function
=
2465 g_array_index(process
->user_stack
, guint64
, depth
- 2);
2469 static gboolean
function_entry(void *hook_data
, void *call_data
)
2471 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2472 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2473 guint8 fac_id
= ltt_event_facility_id(e
);
2474 guint8 ev_id
= ltt_event_eventtype_id(e
);
2475 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2476 g_assert(thf
->f1
!= NULL
);
2477 LttField
*f
= thf
->f1
;
2478 guint64 funcptr
= ltt_event_get_long_unsigned(e
, f
);
2480 push_function(s
, funcptr
);
2484 static gboolean
function_exit(void *hook_data
, void *call_data
)
2486 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2487 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2488 guint8 fac_id
= ltt_event_facility_id(e
);
2489 guint8 ev_id
= ltt_event_eventtype_id(e
);
2490 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2491 g_assert(thf
->f1
!= NULL
);
2492 LttField
*f
= thf
->f1
;
2493 guint64 funcptr
= ltt_event_get_long_unsigned(e
, f
);
2495 LttvExecutionSubmode submode
;
2497 pop_function(s
, funcptr
);
2501 static gboolean
schedchange(void *hook_data
, void *call_data
)
2503 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2505 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2506 LttvProcessState
*process
= ts
->running_process
[cpu
];
2507 LttvProcessState
*old_process
= ts
->running_process
[cpu
];
2509 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2510 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2511 guint pid_in
, pid_out
;
2514 pid_out
= ltt_event_get_unsigned(e
, thf
->f1
);
2515 pid_in
= ltt_event_get_unsigned(e
, thf
->f2
);
2516 state_out
= ltt_event_get_long_int(e
, thf
->f3
);
2518 if(likely(process
!= NULL
)) {
2520 /* We could not know but it was not the idle process executing.
2521 This should only happen at the beginning, before the first schedule
2522 event, and when the initial information (current process for each CPU)
2523 is missing. It is not obvious how we could, after the fact, compensate
2524 the wrongly attributed statistics. */
2526 //This test only makes sense once the state is known and if there is no
2527 //missing events. We need to silently ignore schedchange coming after a
2528 //process_free, or it causes glitches. (FIXME)
2529 //if(unlikely(process->pid != pid_out)) {
2530 // g_assert(process->pid == 0);
2532 if(process
->pid
== 0
2533 && process
->state
->t
== LTTV_STATE_MODE_UNKNOWN
) {
2535 /* Scheduling out of pid 0 at beginning of the trace :
2536 * we know for sure it is in syscall mode at this point. */
2537 g_assert(process
->execution_stack
->len
== 1);
2538 process
->state
->t
= LTTV_STATE_SYSCALL
;
2539 process
->state
->s
= LTTV_STATE_WAIT
;
2540 process
->state
->change
= s
->parent
.timestamp
;
2541 process
->state
->entry
= s
->parent
.timestamp
;
2544 if(unlikely(process
->state
->s
== LTTV_STATE_EXIT
)) {
2545 process
->state
->s
= LTTV_STATE_ZOMBIE
;
2546 process
->state
->change
= s
->parent
.timestamp
;
2548 if(unlikely(state_out
== 0)) process
->state
->s
= LTTV_STATE_WAIT_CPU
;
2549 else process
->state
->s
= LTTV_STATE_WAIT
;
2550 process
->state
->change
= s
->parent
.timestamp
;
2553 if(state_out
== 32 || state_out
== 128)
2554 exit_process(s
, process
); /* EXIT_DEAD || TASK_DEAD */
2555 /* see sched.h for states */
2558 process
= ts
->running_process
[cpu
] =
2559 lttv_state_find_process_or_create(
2560 (LttvTraceState
*)s
->parent
.t_context
,
2562 &s
->parent
.timestamp
);
2563 process
->state
->s
= LTTV_STATE_RUN
;
2565 if(process
->usertrace
)
2566 process
->usertrace
->cpu
= cpu
;
2567 // process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)s)->tf);
2568 process
->state
->change
= s
->parent
.timestamp
;
2570 /* update cpu status */
2572 cpu_set_base_mode(s
->cpu_state
, LTTV_CPU_IDLE
);
2574 cpu_set_base_mode(s
->cpu_state
, LTTV_CPU_BUSY
);
2579 static gboolean
process_fork(void *hook_data
, void *call_data
)
2581 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2582 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2583 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2585 guint child_pid
; /* In the Linux Kernel, there is one PID per thread. */
2586 guint child_tgid
; /* tgid in the Linux kernel is the "real" POSIX PID. */
2587 LttvProcessState
*zombie_process
;
2589 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2590 LttvProcessState
*process
= ts
->running_process
[cpu
];
2591 LttvProcessState
*child_process
;
2594 parent_pid
= ltt_event_get_unsigned(e
, thf
->f1
);
2597 child_pid
= ltt_event_get_unsigned(e
, thf
->f2
);
2598 s
->parent
.target_pid
= child_pid
;
2601 if(thf
->f3
) child_tgid
= ltt_event_get_unsigned(e
, thf
->f3
);
2602 else child_tgid
= 0;
2604 /* Mathieu : it seems like the process might have been scheduled in before the
2605 * fork, and, in a rare case, might be the current process. This might happen
2606 * in a SMP case where we don't have enough precision on the clocks.
2608 * Test reenabled after precision fixes on time. (Mathieu) */
2610 zombie_process
= lttv_state_find_process(ts
, ANY_CPU
, child_pid
);
2612 if(unlikely(zombie_process
!= NULL
)) {
2613 /* Reutilisation of PID. Only now we are sure that the old PID
2614 * has been released. FIXME : should know when release_task happens instead.
2616 guint num_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
2618 for(i
=0; i
< num_cpus
; i
++) {
2619 g_assert(zombie_process
!= ts
->running_process
[i
]);
2622 exit_process(s
, zombie_process
);
2625 g_assert(process
->pid
!= child_pid
);
2626 // FIXME : Add this test in the "known state" section
2627 // g_assert(process->pid == parent_pid);
2628 child_process
= lttv_state_find_process(ts
, ANY_CPU
, child_pid
);
2629 if(child_process
== NULL
) {
2630 child_process
= lttv_state_create_process(ts
, process
, cpu
,
2631 child_pid
, child_tgid
,
2632 LTTV_STATE_UNNAMED
, &s
->parent
.timestamp
);
2634 /* The process has already been created : due to time imprecision between
2635 * multiple CPUs : it has been scheduled in before creation. Note that we
2636 * shouldn't have this kind of imprecision.
2638 * Simply put a correct parent.
2640 g_assert(0); /* This is a problematic case : the process has been created
2641 before the fork event */
2642 child_process
->ppid
= process
->pid
;
2643 child_process
->tgid
= child_tgid
;
2645 g_assert(child_process
->name
== LTTV_STATE_UNNAMED
);
2646 child_process
->name
= process
->name
;
2647 child_process
->brand
= process
->brand
;
2652 /* We stamp a newly created process as kernel_thread.
2653 * The thread should not be running yet. */
2654 static gboolean
process_kernel_thread(void *hook_data
, void *call_data
)
2656 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2657 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2658 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2661 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2662 LttvProcessState
*process
;
2663 LttvExecutionState
*es
;
2666 pid
= (guint
)ltt_event_get_long_unsigned(e
, thf
->f1
);
2667 s
->parent
.target_pid
= pid
;
2669 process
= lttv_state_find_process_or_create(ts
, ANY_CPU
, pid
,
2671 process
->execution_stack
=
2672 g_array_set_size(process
->execution_stack
, 1);
2673 es
= process
->state
=
2674 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
2675 es
->t
= LTTV_STATE_SYSCALL
;
2676 process
->type
= LTTV_STATE_KERNEL_THREAD
;
2681 static gboolean
process_exit(void *hook_data
, void *call_data
)
2683 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2684 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2685 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2689 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2690 LttvProcessState
*process
; // = ts->running_process[cpu];
2692 pid
= ltt_event_get_unsigned(e
, thf
->f1
);
2693 s
->parent
.target_pid
= pid
;
2695 // FIXME : Add this test in the "known state" section
2696 // g_assert(process->pid == pid);
2698 process
= lttv_state_find_process(ts
, ANY_CPU
, pid
);
2699 if(likely(process
!= NULL
)) {
2700 process
->state
->s
= LTTV_STATE_EXIT
;
2705 static gboolean
process_free(void *hook_data
, void *call_data
)
2707 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2708 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2709 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2710 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2712 LttvProcessState
*process
;
2714 /* PID of the process to release */
2715 release_pid
= ltt_event_get_unsigned(e
, thf
->f1
);
2716 s
->parent
.target_pid
= release_pid
;
2718 g_assert(release_pid
!= 0);
2720 process
= lttv_state_find_process(ts
, ANY_CPU
, release_pid
);
2722 if(likely(process
!= NULL
)) {
2723 /* release_task is happening at kernel level : we can now safely release
2724 * the data structure of the process */
2725 //This test is fun, though, as it may happen that
2726 //at time t : CPU 0 : process_free
2727 //at time t+150ns : CPU 1 : schedule out
2728 //Clearly due to time imprecision, we disable it. (Mathieu)
2729 //If this weird case happen, we have no choice but to put the
2730 //Currently running process on the cpu to 0.
2731 //I re-enable it following time precision fixes. (Mathieu)
2732 //Well, in the case where an process is freed by a process on another CPU
2733 //and still scheduled, it happens that this is the schedchange that will
2734 //drop the last reference count. Do not free it here!
2735 guint num_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
2737 for(i
=0; i
< num_cpus
; i
++) {
2738 //g_assert(process != ts->running_process[i]);
2739 if(process
== ts
->running_process
[i
]) {
2740 //ts->running_process[i] = lttv_state_find_process(ts, i, 0);
2744 if(i
== num_cpus
) /* process is not scheduled */
2745 exit_process(s
, process
);
2752 static gboolean
process_exec(void *hook_data
, void *call_data
)
2754 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2755 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2756 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2757 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2760 LttvProcessState
*process
= ts
->running_process
[cpu
];
2762 #if 0//how to use a sequence that must be transformed in a string
2763 /* PID of the process to release */
2764 guint64 name_len
= ltt_event_field_element_number(e
, thf
->f1
);
2765 //name = ltt_event_get_string(e, thf->f1);
2766 LttField
*child
= ltt_event_field_element_select(e
, thf
->f1
, 0);
2768 (gchar
*)(ltt_event_data(e
)+ltt_event_field_offset(e
, child
));
2769 gchar
*null_term_name
= g_new(gchar
, name_len
+1);
2770 memcpy(null_term_name
, name_begin
, name_len
);
2771 null_term_name
[name_len
] = '\0';
2772 process
->name
= g_quark_from_string(null_term_name
);
2775 process
->name
= g_quark_from_string(ltt_event_get_string(e
, thf
->f1
));
2776 process
->brand
= LTTV_STATE_UNBRANDED
;
2777 //g_free(null_term_name);
2781 static gboolean
thread_brand(void *hook_data
, void *call_data
)
2783 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2784 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2785 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2786 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2789 LttvProcessState
*process
= ts
->running_process
[cpu
];
2791 name
= ltt_event_get_string(e
, thf
->f1
);
2792 process
->brand
= g_quark_from_string(name
);
2797 static void fix_process(gpointer key
, gpointer value
,
2800 LttvProcessState
*process
;
2801 LttvExecutionState
*es
;
2802 process
= (LttvProcessState
*)value
;
2803 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)user_data
;
2804 LttTime
*timestamp
= (LttTime
*)user_data
;
2806 if(process
->type
== LTTV_STATE_KERNEL_THREAD
) {
2807 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
2808 if(es
->t
== LTTV_STATE_MODE_UNKNOWN
) {
2809 es
->t
= LTTV_STATE_SYSCALL
;
2810 es
->n
= LTTV_STATE_SUBMODE_NONE
;
2811 es
->entry
= *timestamp
;
2812 es
->change
= *timestamp
;
2813 es
->cum_cpu_time
= ltt_time_zero
;
2814 if(es
->s
== LTTV_STATE_UNNAMED
)
2815 es
->s
= LTTV_STATE_WAIT
;
2818 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
2819 if(es
->t
== LTTV_STATE_MODE_UNKNOWN
) {
2820 es
->t
= LTTV_STATE_USER_MODE
;
2821 es
->n
= LTTV_STATE_SUBMODE_NONE
;
2822 es
->entry
= *timestamp
;
2823 //g_assert(timestamp->tv_sec != 0);
2824 es
->change
= *timestamp
;
2825 es
->cum_cpu_time
= ltt_time_zero
;
2826 if(es
->s
== LTTV_STATE_UNNAMED
)
2827 es
->s
= LTTV_STATE_RUN
;
2829 if(process
->execution_stack
->len
== 1) {
2830 /* Still in bottom unknown mode, means never did a system call
2831 * May be either in user mode, syscall mode, running or waiting.*/
2832 /* FIXME : we may be tagging syscall mode when being user mode */
2833 process
->execution_stack
=
2834 g_array_set_size(process
->execution_stack
, 2);
2835 es
= process
->state
= &g_array_index(process
->execution_stack
,
2836 LttvExecutionState
, 1);
2837 es
->t
= LTTV_STATE_SYSCALL
;
2838 es
->n
= LTTV_STATE_SUBMODE_NONE
;
2839 es
->entry
= *timestamp
;
2840 //g_assert(timestamp->tv_sec != 0);
2841 es
->change
= *timestamp
;
2842 es
->cum_cpu_time
= ltt_time_zero
;
2843 if(es
->s
== LTTV_STATE_WAIT_FORK
)
2844 es
->s
= LTTV_STATE_WAIT
;
2850 static gboolean
statedump_end(void *hook_data
, void *call_data
)
2852 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2853 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2854 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
2855 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2856 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2858 /* For all processes */
2859 /* if kernel thread, if stack[0] is unknown, set to syscall mode, wait */
2860 /* else, if stack[0] is unknown, set to user mode, running */
2862 g_hash_table_foreach(ts
->processes
, fix_process
, &tfc
->timestamp
);
2865 static gboolean
enum_process_state(void *hook_data
, void *call_data
)
2867 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2868 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2869 //It's slow : optimise later by doing this before reading trace.
2870 LttEventType
*et
= ltt_event_eventtype(e
);
2872 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2878 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2879 LttvProcessState
*process
= ts
->running_process
[cpu
];
2880 LttvProcessState
*parent_process
;
2881 LttField
*f4
, *f5
, *f6
, *f7
, *f8
;
2882 GQuark type
, mode
, submode
, status
;
2883 LttvExecutionState
*es
;
2887 pid
= ltt_event_get_unsigned(e
, thf
->f1
);
2888 s
->parent
.target_pid
= pid
;
2891 parent_pid
= ltt_event_get_unsigned(e
, thf
->f2
);
2894 command
= ltt_event_get_string(e
, thf
->f3
);
2897 f4
= ltt_eventtype_field_by_name(et
, LTT_FIELD_TYPE
);
2898 type
= ltt_enum_string_get(ltt_field_type(f4
),
2899 ltt_event_get_unsigned(e
, f4
));
2902 f5
= ltt_eventtype_field_by_name(et
, LTT_FIELD_MODE
);
2903 mode
= ltt_enum_string_get(ltt_field_type(f5
),
2904 ltt_event_get_unsigned(e
, f5
));
2907 f6
= ltt_eventtype_field_by_name(et
, LTT_FIELD_SUBMODE
);
2908 submode
= ltt_enum_string_get(ltt_field_type(f6
),
2909 ltt_event_get_unsigned(e
, f6
));
2912 f7
= ltt_eventtype_field_by_name(et
, LTT_FIELD_STATUS
);
2913 status
= ltt_enum_string_get(ltt_field_type(f7
),
2914 ltt_event_get_unsigned(e
, f7
));
2917 f8
= ltt_eventtype_field_by_name(et
, LTT_FIELD_TGID
);
2918 if(f8
) tgid
= ltt_event_get_unsigned(e
, f8
);
2923 nb_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
2924 for(i
=0; i
<nb_cpus
; i
++) {
2925 process
= lttv_state_find_process(ts
, i
, pid
);
2926 g_assert(process
!= NULL
);
2928 process
->ppid
= parent_pid
;
2929 process
->tgid
= tgid
;
2930 process
->name
= g_quark_from_string(command
);
2932 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
2933 process
->type
= LTTV_STATE_KERNEL_THREAD
;
2937 /* The process might exist if a process was forked while performing the
2939 process
= lttv_state_find_process(ts
, ANY_CPU
, pid
);
2940 if(process
== NULL
) {
2941 parent_process
= lttv_state_find_process(ts
, ANY_CPU
, parent_pid
);
2942 process
= lttv_state_create_process(ts
, parent_process
, cpu
,
2943 pid
, tgid
, g_quark_from_string(command
),
2944 &s
->parent
.timestamp
);
2946 /* Keep the stack bottom : a running user mode */
2947 /* Disabled because of inconsistencies in the current statedump states. */
2948 if(type
== LTTV_STATE_KERNEL_THREAD
) {
2949 /* Only keep the bottom
2950 * FIXME Kernel thread : can be in syscall or interrupt or trap. */
2951 /* Will cause expected trap when in fact being syscall (even after end of
2953 * Will cause expected interrupt when being syscall. (only before end of
2954 * statedump event) */
2955 // This will cause a "popping last state on stack, ignoring it."
2956 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 1);
2957 es
= process
->state
= &g_array_index(process
->execution_stack
,
2958 LttvExecutionState
, 0);
2959 process
->type
= LTTV_STATE_KERNEL_THREAD
;
2960 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
2961 es
->s
= LTTV_STATE_UNNAMED
;
2962 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
2964 es
->t
= LTTV_STATE_SYSCALL
;
2969 /* User space process :
2970 * bottom : user mode
2971 * either currently running or scheduled out.
2972 * can be scheduled out because interrupted in (user mode or in syscall)
2973 * or because of an explicit call to the scheduler in syscall. Note that
2974 * the scheduler call comes after the irq_exit, so never in interrupt
2976 // temp workaround : set size to 1 : only have user mode bottom of stack.
2977 // will cause g_info message of expected syscall mode when in fact being
2978 // in user mode. Can also cause expected trap when in fact being user
2979 // mode in the event of a page fault reenabling interrupts in the handler.
2980 // Expected syscall and trap can also happen after the end of statedump
2981 // This will cause a "popping last state on stack, ignoring it."
2982 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 1);
2983 es
= process
->state
= &g_array_index(process
->execution_stack
,
2984 LttvExecutionState
, 0);
2985 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
2986 es
->s
= LTTV_STATE_UNNAMED
;
2987 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
2989 es
->t
= LTTV_STATE_USER_MODE
;
2997 es
= process
->state
= &g_array_index(process
->execution_stack
,
2998 LttvExecutionState
, 1);
2999 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
3000 es
->s
= LTTV_STATE_UNNAMED
;
3001 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3005 /* The process has already been created :
3006 * Probably was forked while dumping the process state or
3007 * was simply scheduled in prior to get the state dump event.
3009 process
->ppid
= parent_pid
;
3010 process
->tgid
= tgid
;
3011 process
->name
= g_quark_from_string(command
);
3012 process
->type
= type
;
3014 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3016 if(es
->t
== LTTV_STATE_MODE_UNKNOWN
) {
3017 if(type
== LTTV_STATE_KERNEL_THREAD
)
3018 es
->t
= LTTV_STATE_SYSCALL
;
3020 es
->t
= LTTV_STATE_USER_MODE
;
3023 /* Don't mess around with the stack, it will eventually become
3024 * ok after the end of state dump. */
3031 gint
lttv_state_hook_add_event_hooks(void *hook_data
, void *call_data
)
3033 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
3035 lttv_state_add_event_hooks(tss
);
3040 void lttv_state_add_event_hooks(LttvTracesetState
*self
)
3042 LttvTraceset
*traceset
= self
->parent
.ts
;
3044 guint i
, j
, k
, l
, nb_trace
, nb_tracefile
;
3048 LttvTracefileState
*tfs
;
3052 LttvTraceHookByFacility
*thf
;
3054 LttvTraceHook
*hook
;
3056 LttvAttributeValue val
;
3061 nb_trace
= lttv_traceset_number(traceset
);
3062 for(i
= 0 ; i
< nb_trace
; i
++) {
3063 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
3065 /* Find the eventtype id for the following events and register the
3066 associated by id hooks. */
3068 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 19);
3069 hooks
= g_array_set_size(hooks
, 19); // Max possible number of hooks.
3072 ret
= lttv_trace_find_hook(ts
->parent
.t
,
3073 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_SYSCALL_ENTRY
,
3074 LTT_FIELD_SYSCALL_ID
, 0, 0,
3075 syscall_entry
, NULL
, &g_array_index(hooks
, LttvTraceHook
, hn
++));
3078 ret
= lttv_trace_find_hook(ts
->parent
.t
,
3079 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_SYSCALL_EXIT
,
3081 syscall_exit
, NULL
, &g_array_index(hooks
, LttvTraceHook
, hn
++));
3084 ret
= lttv_trace_find_hook(ts
->parent
.t
,
3085 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_TRAP_ENTRY
,
3086 LTT_FIELD_TRAP_ID
, 0, 0,
3087 trap_entry
, NULL
, &g_array_index(hooks
, LttvTraceHook
, hn
++));
3090 ret
= lttv_trace_find_hook(ts
->parent
.t
,
3091 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_TRAP_EXIT
,
3093 trap_exit
, NULL
, &g_array_index(hooks
, LttvTraceHook
, hn
++));
3096 ret
= lttv_trace_find_hook(ts
->parent
.t
,
3097 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_ENTRY
,
3098 LTT_FIELD_IRQ_ID
, 0, 0,
3099 irq_entry
, NULL
, &g_array_index(hooks
, LttvTraceHook
, hn
++));
3102 ret
= lttv_trace_find_hook(ts
->parent
.t
,
3103 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_EXIT
,
3105 irq_exit
, NULL
, &g_array_index(hooks
, LttvTraceHook
, hn
++));
3108 ret
= lttv_trace_find_hook(ts
->parent
.t
,
3109 LTT_FACILITY_KERNEL
, LTT_EVENT_SOFT_IRQ_ENTRY
,
3110 LTT_FIELD_SOFT_IRQ_ID
, 0, 0,
3111 soft_irq_entry
, NULL
, &g_array_index(hooks
, LttvTraceHook
, hn
++));
3114 ret
= lttv_trace_find_hook(ts
->parent
.t
,
3115 LTT_FACILITY_KERNEL
, LTT_EVENT_SOFT_IRQ_EXIT
,
3117 soft_irq_exit
, NULL
, &g_array_index(hooks
, LttvTraceHook
, hn
++));
3120 ret
= lttv_trace_find_hook(ts
->parent
.t
,
3121 LTT_FACILITY_KERNEL
, LTT_EVENT_SCHED_SCHEDULE
,
3122 LTT_FIELD_PREV_PID
, LTT_FIELD_NEXT_PID
, LTT_FIELD_PREV_STATE
,
3123 schedchange
, NULL
, &g_array_index(hooks
, LttvTraceHook
, hn
++));
3126 ret
= lttv_trace_find_hook(ts
->parent
.t
,
3127 LTT_FACILITY_KERNEL
, LTT_EVENT_PROCESS_FORK
,
3128 LTT_FIELD_PARENT_PID
, LTT_FIELD_CHILD_PID
, LTT_FIELD_CHILD_TGID
,
3129 process_fork
, NULL
, &g_array_index(hooks
, LttvTraceHook
, hn
++));
3132 ret
= lttv_trace_find_hook(ts
->parent
.t
,
3133 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_KTHREAD_CREATE
,
3134 LTT_FIELD_PID
, 0, 0,
3135 process_kernel_thread
, NULL
, &g_array_index(hooks
, LttvTraceHook
,
3139 ret
= lttv_trace_find_hook(ts
->parent
.t
,
3140 LTT_FACILITY_KERNEL
, LTT_EVENT_PROCESS_EXIT
,
3141 LTT_FIELD_PID
, 0, 0,
3142 process_exit
, NULL
, &g_array_index(hooks
, LttvTraceHook
, hn
++));
3145 ret
= lttv_trace_find_hook(ts
->parent
.t
,
3146 LTT_FACILITY_KERNEL
, LTT_EVENT_PROCESS_FREE
,
3147 LTT_FIELD_PID
, 0, 0,
3148 process_free
, NULL
, &g_array_index(hooks
, LttvTraceHook
, hn
++));
3151 ret
= lttv_trace_find_hook(ts
->parent
.t
,
3152 LTT_FACILITY_FS
, LTT_EVENT_EXEC
,
3153 LTT_FIELD_FILENAME
, 0, 0,
3154 process_exec
, NULL
, &g_array_index(hooks
, LttvTraceHook
, hn
++));
3157 ret
= lttv_trace_find_hook(ts
->parent
.t
,
3158 LTT_FACILITY_USER_GENERIC
, LTT_EVENT_THREAD_BRAND
,
3159 LTT_FIELD_NAME
, 0, 0,
3160 thread_brand
, NULL
, &g_array_index(hooks
, LttvTraceHook
, hn
++));
3163 /* statedump-related hooks */
3164 ret
= lttv_trace_find_hook(ts
->parent
.t
,
3165 LTT_FACILITY_LIST
, LTT_EVENT_PROCESS_STATE
,
3166 LTT_FIELD_PID
, LTT_FIELD_PARENT_PID
, LTT_FIELD_NAME
,
3167 enum_process_state
, NULL
, &g_array_index(hooks
, LttvTraceHook
, hn
++));
3170 ret
= lttv_trace_find_hook(ts
->parent
.t
,
3171 LTT_FACILITY_LIST
, LTT_EVENT_STATEDUMP_END
,
3173 statedump_end
, NULL
, &g_array_index(hooks
, LttvTraceHook
, hn
++));
3176 ret
= lttv_trace_find_hook(ts
->parent
.t
,
3177 LTT_FACILITY_BLOCK
, LTT_EVENT_REQUEST_ISSUE
,
3178 LTT_FIELD_MAJOR
, LTT_FIELD_MINOR
, LTT_FIELD_OPERATION
,
3179 bdev_request_issue
, NULL
, &g_array_index(hooks
, LttvTraceHook
, hn
++));
3182 ret
= lttv_trace_find_hook(ts
->parent
.t
,
3183 LTT_FACILITY_BLOCK
, LTT_EVENT_REQUEST_COMPLETE
,
3184 LTT_FIELD_MAJOR
, LTT_FIELD_MINOR
, LTT_FIELD_OPERATION
,
3185 bdev_request_complete
, NULL
, &g_array_index(hooks
, LttvTraceHook
, hn
++));
3188 ret
= lttv_trace_find_hook(ts
->parent
.t
,
3189 LTT_FACILITY_USER_GENERIC
, LTT_EVENT_FUNCTION_ENTRY
,
3190 LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
, 0,
3191 function_entry
, NULL
, &g_array_index(hooks
, LttvTraceHook
, hn
++));
3194 ret
= lttv_trace_find_hook(ts
->parent
.t
,
3195 LTT_FACILITY_USER_GENERIC
, LTT_EVENT_FUNCTION_EXIT
,
3196 LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
, 0,
3197 function_exit
, NULL
, &g_array_index(hooks
, LttvTraceHook
, hn
++));
3200 hooks
= g_array_set_size(hooks
, hn
);
3202 /* Add these hooks to each event_by_id hooks list */
3204 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3206 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3208 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
3209 LttvTracefileContext
*, j
));
3211 for(k
= 0 ; k
< hooks
->len
; k
++) {
3212 hook
= &g_array_index(hooks
, LttvTraceHook
, k
);
3213 for(l
=0;l
<hook
->fac_list
->len
;l
++) {
3214 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
3216 lttv_hooks_by_id_find(tfs
->parent
.event_by_id
, thf
->id
),
3223 lttv_attribute_find(ts
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
3224 *(val
.v_pointer
) = hooks
;
3228 gint
lttv_state_hook_remove_event_hooks(void *hook_data
, void *call_data
)
3230 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
3232 lttv_state_remove_event_hooks(tss
);
3237 void lttv_state_remove_event_hooks(LttvTracesetState
*self
)
3239 LttvTraceset
*traceset
= self
->parent
.ts
;
3241 guint i
, j
, k
, l
, nb_trace
, nb_tracefile
;
3245 LttvTracefileState
*tfs
;
3249 LttvTraceHook
*hook
;
3251 LttvTraceHookByFacility
*thf
;
3253 LttvAttributeValue val
;
3255 nb_trace
= lttv_traceset_number(traceset
);
3256 for(i
= 0 ; i
< nb_trace
; i
++) {
3257 ts
= LTTV_TRACE_STATE(self
->parent
.traces
[i
]);
3259 lttv_attribute_find(ts
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
3260 hooks
= *(val
.v_pointer
);
3262 /* Remove these hooks from each event_by_id hooks list */
3264 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3266 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3268 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
3269 LttvTracefileContext
*, j
));
3271 for(k
= 0 ; k
< hooks
->len
; k
++) {
3272 hook
= &g_array_index(hooks
, LttvTraceHook
, k
);
3273 for(l
=0;l
<hook
->fac_list
->len
;l
++) {
3274 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
3276 lttv_hooks_remove_data(
3277 lttv_hooks_by_id_find(tfs
->parent
.event_by_id
, thf
->id
),
3283 for(k
= 0 ; k
< hooks
->len
; k
++)
3284 lttv_trace_hook_destroy(&g_array_index(hooks
, LttvTraceHook
, k
));
3285 g_array_free(hooks
, TRUE
);
3289 static gboolean
state_save_event_hook(void *hook_data
, void *call_data
)
3291 guint
*event_count
= (guint
*)hook_data
;
3293 /* Only save at LTTV_STATE_SAVE_INTERVAL */
3294 if(likely((*event_count
)++ < LTTV_STATE_SAVE_INTERVAL
))
3299 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3301 LttvTracefileState
*tfcs
;
3303 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3305 LttEventPosition
*ep
;
3311 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
3313 LttvAttributeValue value
;
3315 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
3316 LTTV_STATE_SAVED_STATES
);
3317 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
3318 value
= lttv_attribute_add(saved_states_tree
,
3319 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
3320 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
3321 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
3322 *(value
.v_time
) = self
->parent
.timestamp
;
3323 lttv_state_save(tcs
, saved_state_tree
);
3324 g_debug("Saving state at time %lu.%lu", self
->parent
.timestamp
.tv_sec
,
3325 self
->parent
.timestamp
.tv_nsec
);
3327 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
3332 static gboolean
state_save_after_trace_hook(void *hook_data
, void *call_data
)
3334 LttvTraceState
*tcs
= (LttvTraceState
*)(call_data
);
3336 *(tcs
->max_time_state_recomputed_in_seek
) = tcs
->parent
.time_span
.end_time
;
3341 guint
lttv_state_current_cpu(LttvTracefileState
*tfs
)
3349 static gboolean
block_start(void *hook_data
, void *call_data
)
3351 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3353 LttvTracefileState
*tfcs
;
3355 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3357 LttEventPosition
*ep
;
3359 guint i
, nb_block
, nb_event
, nb_tracefile
;
3363 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
3365 LttvAttributeValue value
;
3367 ep
= ltt_event_position_new();
3369 nb_tracefile
= tcs
->parent
.tracefiles
->len
;
3371 /* Count the number of events added since the last block end in any
3374 for(i
= 0 ; i
< nb_tracefile
; i
++) {
3376 LTTV_TRACEFILE_STATE(&g_array_index(tcs
->parent
.tracefiles
,
3377 LttvTracefileContext
, i
));
3378 ltt_event_position(tfcs
->parent
.e
, ep
);
3379 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
3380 tcs
->nb_event
+= nb_event
- tfcs
->saved_position
;
3381 tfcs
->saved_position
= nb_event
;
3385 if(tcs
->nb_event
>= tcs
->save_interval
) {
3386 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
3387 LTTV_STATE_SAVED_STATES
);
3388 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
3389 value
= lttv_attribute_add(saved_states_tree
,
3390 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
3391 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
3392 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
3393 *(value
.v_time
) = self
->parent
.timestamp
;
3394 lttv_state_save(tcs
, saved_state_tree
);
3396 g_debug("Saving state at time %lu.%lu", self
->parent
.timestamp
.tv_sec
,
3397 self
->parent
.timestamp
.tv_nsec
);
3399 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
3405 static gboolean
block_end(void *hook_data
, void *call_data
)
3407 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3409 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3413 LttEventPosition
*ep
;
3415 guint nb_block
, nb_event
;
3417 ep
= ltt_event_position_new();
3418 ltt_event_position(self
->parent
.e
, ep
);
3419 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
3420 tcs
->nb_event
+= nb_event
- self
->saved_position
+ 1;
3421 self
->saved_position
= 0;
3422 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
3429 void lttv_state_save_add_event_hooks(LttvTracesetState
*self
)
3431 LttvTraceset
*traceset
= self
->parent
.ts
;
3433 guint i
, j
, nb_trace
, nb_tracefile
;
3437 LttvTracefileState
*tfs
;
3439 LttvTraceHook hook_start
, hook_end
;
3441 nb_trace
= lttv_traceset_number(traceset
);
3442 for(i
= 0 ; i
< nb_trace
; i
++) {
3443 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
3445 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
3446 NULL
, NULL
, block_start
, &hook_start
);
3447 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
3448 NULL
, NULL
, block_end
, &hook_end
);
3450 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3452 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3454 LTTV_TRACEFILE_STATE(&g_array_index(ts
->parent
.tracefiles
,
3455 LttvTracefileContext
, j
));
3456 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
3457 hook_start
.id
), hook_start
.h
, NULL
, LTTV_PRIO_STATE
);
3458 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
3459 hook_end
.id
), hook_end
.h
, NULL
, LTTV_PRIO_STATE
);
3465 void lttv_state_save_add_event_hooks(LttvTracesetState
*self
)
3467 LttvTraceset
*traceset
= self
->parent
.ts
;
3469 guint i
, j
, nb_trace
, nb_tracefile
;
3473 LttvTracefileState
*tfs
;
3476 nb_trace
= lttv_traceset_number(traceset
);
3477 for(i
= 0 ; i
< nb_trace
; i
++) {
3479 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
3480 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3482 if(ts
->has_precomputed_states
) continue;
3484 guint
*event_count
= g_new(guint
, 1);
3487 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3489 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
3490 LttvTracefileContext
*, j
));
3491 lttv_hooks_add(tfs
->parent
.event
,
3492 state_save_event_hook
,
3499 lttv_process_traceset_begin(&self
->parent
,
3500 NULL
, NULL
, NULL
, NULL
, NULL
);
3504 gint
lttv_state_save_hook_add_event_hooks(void *hook_data
, void *call_data
)
3506 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
3508 lttv_state_save_add_event_hooks(tss
);
3515 void lttv_state_save_remove_event_hooks(LttvTracesetState
*self
)
3517 LttvTraceset
*traceset
= self
->parent
.ts
;
3519 guint i
, j
, nb_trace
, nb_tracefile
;
3523 LttvTracefileState
*tfs
;
3525 LttvTraceHook hook_start
, hook_end
;
3527 nb_trace
= lttv_traceset_number(traceset
);
3528 for(i
= 0 ; i
< nb_trace
; i
++) {
3529 ts
= LTTV_TRACE_STATE(self
->parent
.traces
[i
]);
3531 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
3532 NULL
, NULL
, block_start
, &hook_start
);
3534 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
3535 NULL
, NULL
, block_end
, &hook_end
);
3537 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3539 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3541 LTTV_TRACEFILE_STATE(&g_array_index(ts
->parent
.tracefiles
,
3542 LttvTracefileContext
, j
));
3543 lttv_hooks_remove_data(lttv_hooks_by_id_find(
3544 tfs
->parent
.event_by_id
, hook_start
.id
), hook_start
.h
, NULL
);
3545 lttv_hooks_remove_data(lttv_hooks_by_id_find(
3546 tfs
->parent
.event_by_id
, hook_end
.id
), hook_end
.h
, NULL
);
3552 void lttv_state_save_remove_event_hooks(LttvTracesetState
*self
)
3554 LttvTraceset
*traceset
= self
->parent
.ts
;
3556 guint i
, j
, nb_trace
, nb_tracefile
;
3560 LttvTracefileState
*tfs
;
3562 LttvHooks
*after_trace
= lttv_hooks_new();
3564 lttv_hooks_add(after_trace
,
3565 state_save_after_trace_hook
,
3570 lttv_process_traceset_end(&self
->parent
,
3571 NULL
, after_trace
, NULL
, NULL
, NULL
);
3573 lttv_hooks_destroy(after_trace
);
3575 nb_trace
= lttv_traceset_number(traceset
);
3576 for(i
= 0 ; i
< nb_trace
; i
++) {
3578 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
3579 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3581 if(ts
->has_precomputed_states
) continue;
3583 guint
*event_count
= NULL
;
3585 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3587 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
3588 LttvTracefileContext
*, j
));
3589 event_count
= lttv_hooks_remove(tfs
->parent
.event
,
3590 state_save_event_hook
);
3592 if(event_count
) g_free(event_count
);
3596 gint
lttv_state_save_hook_remove_event_hooks(void *hook_data
, void *call_data
)
3598 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
3600 lttv_state_save_remove_event_hooks(tss
);
3605 void lttv_state_traceset_seek_time_closest(LttvTracesetState
*self
, LttTime t
)
3607 LttvTraceset
*traceset
= self
->parent
.ts
;
3611 int min_pos
, mid_pos
, max_pos
;
3613 guint call_rest
= 0;
3615 LttvTraceState
*tcs
;
3617 LttvAttributeValue value
;
3619 LttvAttributeType type
;
3621 LttvAttributeName name
;
3625 LttvAttribute
*saved_states_tree
, *saved_state_tree
, *closest_tree
;
3627 //g_tree_destroy(self->parent.pqueue);
3628 //self->parent.pqueue = g_tree_new(compare_tracefile);
3630 g_info("Entering seek_time_closest for time %lu.%lu", t
.tv_sec
, t
.tv_nsec
);
3632 nb_trace
= lttv_traceset_number(traceset
);
3633 for(i
= 0 ; i
< nb_trace
; i
++) {
3634 tcs
= (LttvTraceState
*)self
->parent
.traces
[i
];
3636 if(ltt_time_compare(t
, *(tcs
->max_time_state_recomputed_in_seek
)) < 0) {
3637 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
3638 LTTV_STATE_SAVED_STATES
);
3641 if(saved_states_tree
) {
3642 max_pos
= lttv_attribute_get_number(saved_states_tree
) - 1;
3643 mid_pos
= max_pos
/ 2;
3644 while(min_pos
< max_pos
) {
3645 type
= lttv_attribute_get(saved_states_tree
, mid_pos
, &name
, &value
,
3647 g_assert(type
== LTTV_GOBJECT
);
3648 saved_state_tree
= *((LttvAttribute
**)(value
.v_gobject
));
3649 type
= lttv_attribute_get_by_name(saved_state_tree
, LTTV_STATE_TIME
,
3651 g_assert(type
== LTTV_TIME
);
3652 if(ltt_time_compare(*(value
.v_time
), t
) < 0) {
3654 closest_tree
= saved_state_tree
;
3656 else max_pos
= mid_pos
- 1;
3658 mid_pos
= (min_pos
+ max_pos
+ 1) / 2;
3662 /* restore the closest earlier saved state */
3664 lttv_state_restore(tcs
, closest_tree
);
3668 /* There is no saved state, yet we want to have it. Restart at T0 */
3670 restore_init_state(tcs
);
3671 lttv_process_trace_seek_time(&(tcs
->parent
), ltt_time_zero
);
3674 /* We want to seek quickly without restoring/updating the state */
3676 restore_init_state(tcs
);
3677 lttv_process_trace_seek_time(&(tcs
->parent
), t
);
3680 if(!call_rest
) g_info("NOT Calling restore");
3685 traceset_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
3691 traceset_state_finalize (LttvTracesetState
*self
)
3693 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
3694 finalize(G_OBJECT(self
));
3699 traceset_state_class_init (LttvTracesetContextClass
*klass
)
3701 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
3703 gobject_class
->finalize
= (void (*)(GObject
*self
)) traceset_state_finalize
;
3704 klass
->init
= (void (*)(LttvTracesetContext
*self
, LttvTraceset
*ts
))init
;
3705 klass
->fini
= (void (*)(LttvTracesetContext
*self
))fini
;
3706 klass
->new_traceset_context
= new_traceset_context
;
3707 klass
->new_trace_context
= new_trace_context
;
3708 klass
->new_tracefile_context
= new_tracefile_context
;
3713 lttv_traceset_state_get_type(void)
3715 static GType type
= 0;
3717 static const GTypeInfo info
= {
3718 sizeof (LttvTracesetStateClass
),
3719 NULL
, /* base_init */
3720 NULL
, /* base_finalize */
3721 (GClassInitFunc
) traceset_state_class_init
, /* class_init */
3722 NULL
, /* class_finalize */
3723 NULL
, /* class_data */
3724 sizeof (LttvTracesetState
),
3725 0, /* n_preallocs */
3726 (GInstanceInitFunc
) traceset_state_instance_init
, /* instance_init */
3727 NULL
/* value handling */
3730 type
= g_type_register_static (LTTV_TRACESET_CONTEXT_TYPE
, "LttvTracesetStateType",
3738 trace_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
3744 trace_state_finalize (LttvTraceState
*self
)
3746 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_CONTEXT_TYPE
))->
3747 finalize(G_OBJECT(self
));
3752 trace_state_class_init (LttvTraceStateClass
*klass
)
3754 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
3756 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_state_finalize
;
3757 klass
->state_save
= state_save
;
3758 klass
->state_restore
= state_restore
;
3759 klass
->state_saved_free
= state_saved_free
;
3764 lttv_trace_state_get_type(void)
3766 static GType type
= 0;
3768 static const GTypeInfo info
= {
3769 sizeof (LttvTraceStateClass
),
3770 NULL
, /* base_init */
3771 NULL
, /* base_finalize */
3772 (GClassInitFunc
) trace_state_class_init
, /* class_init */
3773 NULL
, /* class_finalize */
3774 NULL
, /* class_data */
3775 sizeof (LttvTraceState
),
3776 0, /* n_preallocs */
3777 (GInstanceInitFunc
) trace_state_instance_init
, /* instance_init */
3778 NULL
/* value handling */
3781 type
= g_type_register_static (LTTV_TRACE_CONTEXT_TYPE
,
3782 "LttvTraceStateType", &info
, 0);
3789 tracefile_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
3795 tracefile_state_finalize (LttvTracefileState
*self
)
3797 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_CONTEXT_TYPE
))->
3798 finalize(G_OBJECT(self
));
3803 tracefile_state_class_init (LttvTracefileStateClass
*klass
)
3805 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
3807 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_state_finalize
;
3812 lttv_tracefile_state_get_type(void)
3814 static GType type
= 0;
3816 static const GTypeInfo info
= {
3817 sizeof (LttvTracefileStateClass
),
3818 NULL
, /* base_init */
3819 NULL
, /* base_finalize */
3820 (GClassInitFunc
) tracefile_state_class_init
, /* class_init */
3821 NULL
, /* class_finalize */
3822 NULL
, /* class_data */
3823 sizeof (LttvTracefileState
),
3824 0, /* n_preallocs */
3825 (GInstanceInitFunc
) tracefile_state_instance_init
, /* instance_init */
3826 NULL
/* value handling */
3829 type
= g_type_register_static (LTTV_TRACEFILE_CONTEXT_TYPE
,
3830 "LttvTracefileStateType", &info
, 0);
3836 static void module_init()
3838 LTTV_STATE_UNNAMED
= g_quark_from_string("UNNAMED");
3839 LTTV_STATE_UNBRANDED
= g_quark_from_string("UNBRANDED");
3840 LTTV_STATE_MODE_UNKNOWN
= g_quark_from_string("MODE_UNKNOWN");
3841 LTTV_STATE_USER_MODE
= g_quark_from_string("USER_MODE");
3842 LTTV_STATE_SYSCALL
= g_quark_from_string("SYSCALL");
3843 LTTV_STATE_TRAP
= g_quark_from_string("TRAP");
3844 LTTV_STATE_IRQ
= g_quark_from_string("IRQ");
3845 LTTV_STATE_SOFT_IRQ
= g_quark_from_string("SOFTIRQ");
3846 LTTV_STATE_SUBMODE_UNKNOWN
= g_quark_from_string("UNKNOWN");
3847 LTTV_STATE_SUBMODE_NONE
= g_quark_from_string("NONE");
3848 LTTV_STATE_WAIT_FORK
= g_quark_from_string("WAIT_FORK");
3849 LTTV_STATE_WAIT_CPU
= g_quark_from_string("WAIT_CPU");
3850 LTTV_STATE_EXIT
= g_quark_from_string("EXIT");
3851 LTTV_STATE_ZOMBIE
= g_quark_from_string("ZOMBIE");
3852 LTTV_STATE_WAIT
= g_quark_from_string("WAIT");
3853 LTTV_STATE_RUN
= g_quark_from_string("RUN");
3854 LTTV_STATE_DEAD
= g_quark_from_string("DEAD");
3855 LTTV_STATE_USER_THREAD
= g_quark_from_string("USER_THREAD");
3856 LTTV_STATE_KERNEL_THREAD
= g_quark_from_string("KERNEL_THREAD");
3857 LTTV_STATE_TRACEFILES
= g_quark_from_string("tracefiles");
3858 LTTV_STATE_PROCESSES
= g_quark_from_string("processes");
3859 LTTV_STATE_PROCESS
= g_quark_from_string("process");
3860 LTTV_STATE_RUNNING_PROCESS
= g_quark_from_string("running_process");
3861 LTTV_STATE_EVENT
= g_quark_from_string("event");
3862 LTTV_STATE_SAVED_STATES
= g_quark_from_string("saved states");
3863 LTTV_STATE_SAVED_STATES_TIME
= g_quark_from_string("saved states time");
3864 LTTV_STATE_TIME
= g_quark_from_string("time");
3865 LTTV_STATE_HOOKS
= g_quark_from_string("saved state hooks");
3866 LTTV_STATE_NAME_TABLES
= g_quark_from_string("name tables");
3867 LTTV_STATE_TRACE_STATE_USE_COUNT
=
3868 g_quark_from_string("trace_state_use_count");
3869 LTTV_STATE_RESOURCE_CPUS
= g_quark_from_string("cpu resource states");
3870 LTTV_STATE_RESOURCE_IRQS
= g_quark_from_string("irq resource states");
3871 LTTV_STATE_RESOURCE_BLKDEVS
= g_quark_from_string("blkdevs resource states");
3874 LTT_FACILITY_KERNEL
= g_quark_from_string("kernel");
3875 LTT_FACILITY_KERNEL_ARCH
= g_quark_from_string("kernel_arch");
3876 LTT_FACILITY_FS
= g_quark_from_string("fs");
3877 LTT_FACILITY_LIST
= g_quark_from_string("list");
3878 LTT_FACILITY_USER_GENERIC
= g_quark_from_string("user_generic");
3879 LTT_FACILITY_BLOCK
= g_quark_from_string("block");
3882 LTT_EVENT_SYSCALL_ENTRY
= g_quark_from_string("syscall_entry");
3883 LTT_EVENT_SYSCALL_EXIT
= g_quark_from_string("syscall_exit");
3884 LTT_EVENT_TRAP_ENTRY
= g_quark_from_string("trap_entry");
3885 LTT_EVENT_TRAP_EXIT
= g_quark_from_string("trap_exit");
3886 LTT_EVENT_IRQ_ENTRY
= g_quark_from_string("irq_entry");
3887 LTT_EVENT_IRQ_EXIT
= g_quark_from_string("irq_exit");
3888 LTT_EVENT_SOFT_IRQ_ENTRY
= g_quark_from_string("soft_irq_entry");
3889 LTT_EVENT_SOFT_IRQ_EXIT
= g_quark_from_string("soft_irq_exit");
3890 LTT_EVENT_SCHED_SCHEDULE
= g_quark_from_string("sched_schedule");
3891 LTT_EVENT_PROCESS_FORK
= g_quark_from_string("process_fork");
3892 LTT_EVENT_KTHREAD_CREATE
= g_quark_from_string("kthread_create");
3893 LTT_EVENT_PROCESS_EXIT
= g_quark_from_string("process_exit");
3894 LTT_EVENT_PROCESS_FREE
= g_quark_from_string("process_free");
3895 LTT_EVENT_EXEC
= g_quark_from_string("exec");
3896 LTT_EVENT_PROCESS_STATE
= g_quark_from_string("process_state");
3897 LTT_EVENT_STATEDUMP_END
= g_quark_from_string("statedump_end");
3898 LTT_EVENT_FUNCTION_ENTRY
= g_quark_from_string("function_entry");
3899 LTT_EVENT_FUNCTION_EXIT
= g_quark_from_string("function_exit");
3900 LTT_EVENT_THREAD_BRAND
= g_quark_from_string("thread_brand");
3901 LTT_EVENT_REQUEST_ISSUE
= g_quark_from_string("_blk_request_issue");
3902 LTT_EVENT_REQUEST_COMPLETE
= g_quark_from_string("_blk_request_complete");
3905 LTT_FIELD_SYSCALL_ID
= g_quark_from_string("syscall_id");
3906 LTT_FIELD_TRAP_ID
= g_quark_from_string("trap_id");
3907 LTT_FIELD_IRQ_ID
= g_quark_from_string("irq_id");
3908 LTT_FIELD_SOFT_IRQ_ID
= g_quark_from_string("softirq_id");
3909 LTT_FIELD_PREV_PID
= g_quark_from_string("prev_pid");
3910 LTT_FIELD_NEXT_PID
= g_quark_from_string("next_pid");
3911 LTT_FIELD_PREV_STATE
= g_quark_from_string("prev_state");
3912 LTT_FIELD_PARENT_PID
= g_quark_from_string("parent_pid");
3913 LTT_FIELD_CHILD_PID
= g_quark_from_string("child_pid");
3914 LTT_FIELD_PID
= g_quark_from_string("pid");
3915 LTT_FIELD_TGID
= g_quark_from_string("tgid");
3916 LTT_FIELD_CHILD_TGID
= g_quark_from_string("child_tgid");
3917 LTT_FIELD_FILENAME
= g_quark_from_string("filename");
3918 LTT_FIELD_NAME
= g_quark_from_string("name");
3919 LTT_FIELD_TYPE
= g_quark_from_string("type");
3920 LTT_FIELD_MODE
= g_quark_from_string("mode");
3921 LTT_FIELD_SUBMODE
= g_quark_from_string("submode");
3922 LTT_FIELD_STATUS
= g_quark_from_string("status");
3923 LTT_FIELD_THIS_FN
= g_quark_from_string("this_fn");
3924 LTT_FIELD_CALL_SITE
= g_quark_from_string("call_site");
3925 LTT_FIELD_MAJOR
= g_quark_from_string("major");
3926 LTT_FIELD_MINOR
= g_quark_from_string("minor");
3927 LTT_FIELD_OPERATION
= g_quark_from_string("direction");
3929 LTTV_CPU_UNKNOWN
= g_quark_from_string("unknown");
3930 LTTV_CPU_IDLE
= g_quark_from_string("idle");
3931 LTTV_CPU_BUSY
= g_quark_from_string("busy");
3932 LTTV_CPU_IRQ
= g_quark_from_string("irq");
3933 LTTV_CPU_TRAP
= g_quark_from_string("trap");
3935 LTTV_IRQ_UNKNOWN
= g_quark_from_string("unknown");
3936 LTTV_IRQ_IDLE
= g_quark_from_string("idle");
3937 LTTV_IRQ_BUSY
= g_quark_from_string("busy");
3939 LTTV_BDEV_UNKNOWN
= g_quark_from_string("unknown");
3940 LTTV_BDEV_IDLE
= g_quark_from_string("idle");
3941 LTTV_BDEV_BUSY_READING
= g_quark_from_string("busy_reading");
3942 LTTV_BDEV_BUSY_WRITING
= g_quark_from_string("busy_writing");
3945 static void module_destroy()
3950 LTTV_MODULE("state", "State computation", \
3951 "Update the system state, possibly saving it at intervals", \
3952 module_init
, module_destroy
)