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
));
1218 static void bdevstate_free(LttvBdevState
*bds
)
1220 g_array_free(bds
->mode_stack
, FALSE
);
1224 static void bdevstate_free_cb(gpointer key
, gpointer value
, gpointer user_data
)
1226 LttvBdevState
*bds
= (LttvBdevState
*) value
;
1228 bdevstate_free(bds
);
1231 static LttvBdevState
*bdevstate_copy(LttvBdevState
*bds
)
1233 LttvBdevState
*retval
;
1235 retval
= bdevstate_new();
1236 g_array_insert_vals(retval
->mode_stack
, 0, bds
->mode_stack
->data
, bds
->mode_stack
->len
);
1239 static void insert_and_copy_bdev_state(gpointer k
, gpointer v
, gpointer u
)
1241 GHashTable
*ht
= (GHashTable
*)u
;
1242 LttvBdevState
*bds
= (LttvBdevState
*)v
;
1243 LttvBdevState
*newbds
;
1245 newbds
= bdevstate_copy(v
);
1247 g_hash_table_insert(u
, k
, newbds
);
1250 static GHashTable
*lttv_state_copy_blkdev_hashtable(GHashTable
*ht
)
1254 retval
= g_hash_table_new(g_int_hash
, g_int_equal
);
1256 g_hash_table_foreach(ht
, insert_and_copy_bdev_state
, retval
);
1261 /* Free a hashtable and the LttvBdevState structures its values
1264 static void lttv_state_free_blkdev_hashtable(GHashTable
*ht
)
1266 g_hash_table_foreach(ht
, bdevstate_free_cb
, NULL
);
1267 g_hash_table_destroy(ht
);
1270 /* The saved state for each trace contains a member "processes", which
1271 stores a copy of the process table, and a member "tracefiles" with
1272 one entry per tracefile. Each tracefile has a "process" member pointing
1273 to the current process and a "position" member storing the tracefile
1274 position (needed to seek to the current "next" event. */
1276 static void state_save(LttvTraceState
*self
, LttvAttribute
*container
)
1278 guint i
, nb_tracefile
, nb_cpus
, nb_irqs
;
1280 LttvTracefileState
*tfcs
;
1282 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
1284 guint
*running_process
;
1286 LttvAttributeType type
;
1288 LttvAttributeValue value
;
1290 LttvAttributeName name
;
1292 LttEventPosition
*ep
;
1294 tracefiles_tree
= lttv_attribute_find_subdir(container
,
1295 LTTV_STATE_TRACEFILES
);
1297 value
= lttv_attribute_add(container
, LTTV_STATE_PROCESSES
,
1299 *(value
.v_pointer
) = lttv_state_copy_process_table(self
->processes
);
1301 /* Add the currently running processes array */
1302 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
1303 running_process
= g_new(guint
, nb_cpus
);
1304 for(i
=0;i
<nb_cpus
;i
++) {
1305 running_process
[i
] = self
->running_process
[i
]->pid
;
1307 value
= lttv_attribute_add(container
, LTTV_STATE_RUNNING_PROCESS
,
1309 *(value
.v_pointer
) = running_process
;
1311 g_info("State save");
1313 nb_tracefile
= self
->parent
.tracefiles
->len
;
1315 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1317 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1318 LttvTracefileContext
*, i
));
1319 tracefile_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
1320 value
= lttv_attribute_add(tracefiles_tree
, i
,
1322 *(value
.v_gobject
) = (GObject
*)tracefile_tree
;
1324 value
= lttv_attribute_add(tracefile_tree
, LTTV_STATE_PROCESS
,
1326 *(value
.v_uint
) = tfcs
->process
->pid
;
1328 value
= lttv_attribute_add(tracefile_tree
, LTTV_STATE_EVENT
,
1330 /* Only save the position if the tfs has not infinite time. */
1331 //if(!g_tree_lookup(self->parent.ts_context->pqueue, &tfcs->parent)
1332 // && current_tfcs != tfcs) {
1333 if(ltt_time_compare(tfcs
->parent
.timestamp
, ltt_time_infinite
) == 0) {
1334 *(value
.v_pointer
) = NULL
;
1336 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.tf
);
1337 ep
= ltt_event_position_new();
1338 ltt_event_position(e
, ep
);
1339 *(value
.v_pointer
) = ep
;
1341 guint nb_block
, offset
;
1344 ltt_event_position_get(ep
, &tf
, &nb_block
, &offset
, &tsc
);
1345 g_info("Block %u offset %u tsc %llu time %lu.%lu", nb_block
, offset
,
1347 tfcs
->parent
.timestamp
.tv_sec
, tfcs
->parent
.timestamp
.tv_nsec
);
1351 /* save the cpu state */
1353 guint size
= sizeof(LttvCPUState
)*nb_cpus
;
1354 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_CPUS
,
1356 *(value
.v_pointer
) = lttv_state_copy_cpu_states(self
->cpu_states
, nb_cpus
);
1359 /* save the irq state */
1360 nb_irqs
= self
->nb_irqs
;
1362 guint size
= sizeof(LttvCPUState
)*nb_irqs
;
1363 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_IRQS
,
1365 *(value
.v_pointer
) = lttv_state_copy_irq_states(self
->irq_states
, nb_irqs
);
1368 /* save the blkdev states */
1369 value
= lttv_attribute_add(container
, LTTV_STATE_RESOURCE_BLKDEVS
,
1371 *(value
.v_pointer
) = lttv_state_copy_blkdev_hashtable(self
->bdev_states
);
1375 static void state_restore(LttvTraceState
*self
, LttvAttribute
*container
)
1377 guint i
, nb_tracefile
, pid
, nb_cpus
, nb_irqs
;
1379 LttvTracefileState
*tfcs
;
1381 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
1383 guint
*running_process
;
1385 LttvAttributeType type
;
1387 LttvAttributeValue value
;
1389 LttvAttributeName name
;
1393 LttEventPosition
*ep
;
1395 LttvTracesetContext
*tsc
= self
->parent
.ts_context
;
1397 tracefiles_tree
= lttv_attribute_find_subdir(container
,
1398 LTTV_STATE_TRACEFILES
);
1400 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_PROCESSES
,
1402 g_assert(type
== LTTV_POINTER
);
1403 lttv_state_free_process_table(self
->processes
);
1404 self
->processes
= lttv_state_copy_process_table(*(value
.v_pointer
));
1406 /* Add the currently running processes array */
1407 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
1408 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RUNNING_PROCESS
,
1410 g_assert(type
== LTTV_POINTER
);
1411 running_process
= *(value
.v_pointer
);
1412 for(i
=0;i
<nb_cpus
;i
++) {
1413 pid
= running_process
[i
];
1414 self
->running_process
[i
] = lttv_state_find_process(self
, i
, pid
);
1415 g_assert(self
->running_process
[i
] != NULL
);
1418 nb_tracefile
= self
->parent
.tracefiles
->len
;
1420 //g_tree_destroy(tsc->pqueue);
1421 //tsc->pqueue = g_tree_new(compare_tracefile);
1423 /* restore cpu resource states */
1424 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_CPUS
, &value
);
1425 g_assert(type
== LTTV_POINTER
);
1426 lttv_state_free_cpu_states(self
->cpu_states
, nb_cpus
);
1427 self
->cpu_states
= lttv_state_copy_cpu_states(*(value
.v_pointer
), nb_cpus
);
1429 /* restore irq resource states */
1430 nb_irqs
= self
->nb_irqs
;
1431 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_IRQS
, &value
);
1432 g_assert(type
== LTTV_POINTER
);
1433 lttv_state_free_irq_states(self
->irq_states
, nb_irqs
);
1434 self
->irq_states
= lttv_state_copy_irq_states(*(value
.v_pointer
), nb_irqs
);
1436 /* restore the blkdev states */
1437 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RESOURCE_BLKDEVS
, &value
);
1438 g_assert(type
== LTTV_POINTER
);
1439 lttv_state_free_blkdev_hashtable(self
->bdev_states
);
1440 self
->bdev_states
= lttv_state_copy_blkdev_hashtable(self
->bdev_states
);
1442 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1444 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1445 LttvTracefileContext
*, i
));
1446 type
= lttv_attribute_get(tracefiles_tree
, i
, &name
, &value
, &is_named
);
1447 g_assert(type
== LTTV_GOBJECT
);
1448 tracefile_tree
= *((LttvAttribute
**)(value
.v_gobject
));
1450 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_PROCESS
,
1452 g_assert(type
== LTTV_UINT
);
1453 pid
= *(value
.v_uint
);
1454 tfcs
->process
= lttv_state_find_process_or_create(tfcs
, pid
);
1456 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_EVENT
,
1458 g_assert(type
== LTTV_POINTER
);
1459 //g_assert(*(value.v_pointer) != NULL);
1460 ep
= *(value
.v_pointer
);
1461 g_assert(tfcs
->parent
.t_context
!= NULL
);
1463 tfcs
->cpu_state
= &self
->cpu_states
[tfcs
->cpu
];
1465 LttvTracefileContext
*tfc
= LTTV_TRACEFILE_CONTEXT(tfcs
);
1466 g_tree_remove(tsc
->pqueue
, tfc
);
1469 g_assert(ltt_tracefile_seek_position(tfc
->tf
, ep
) == 0);
1470 tfc
->timestamp
= ltt_event_time(ltt_tracefile_get_event(tfc
->tf
));
1471 g_assert(ltt_time_compare(tfc
->timestamp
, ltt_time_infinite
) != 0);
1472 g_tree_insert(tsc
->pqueue
, tfc
, tfc
);
1473 g_info("Restoring state for a tf at time %lu.%lu", tfc
->timestamp
.tv_sec
, tfc
->timestamp
.tv_nsec
);
1475 tfc
->timestamp
= ltt_time_infinite
;
1481 static void state_saved_free(LttvTraceState
*self
, LttvAttribute
*container
)
1483 guint i
, nb_tracefile
, nb_cpus
;
1485 LttvTracefileState
*tfcs
;
1487 LttvAttribute
*tracefiles_tree
, *tracefile_tree
;
1489 guint
*running_process
;
1491 LttvAttributeType type
;
1493 LttvAttributeValue value
;
1495 LttvAttributeName name
;
1499 LttEventPosition
*ep
;
1501 tracefiles_tree
= lttv_attribute_find_subdir(container
,
1502 LTTV_STATE_TRACEFILES
);
1503 g_object_ref(G_OBJECT(tracefiles_tree
));
1504 lttv_attribute_remove_by_name(container
, LTTV_STATE_TRACEFILES
);
1506 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_PROCESSES
,
1508 g_assert(type
== LTTV_POINTER
);
1509 lttv_state_free_process_table(*(value
.v_pointer
));
1510 *(value
.v_pointer
) = NULL
;
1511 lttv_attribute_remove_by_name(container
, LTTV_STATE_PROCESSES
);
1513 /* Free running processes array */
1514 nb_cpus
= ltt_trace_get_num_cpu(self
->parent
.t
);
1515 type
= lttv_attribute_get_by_name(container
, LTTV_STATE_RUNNING_PROCESS
,
1517 g_assert(type
== LTTV_POINTER
);
1518 running_process
= *(value
.v_pointer
);
1519 g_free(running_process
);
1521 nb_tracefile
= self
->parent
.tracefiles
->len
;
1523 for(i
= 0 ; i
< nb_tracefile
; i
++) {
1525 LTTV_TRACEFILE_STATE(g_array_index(self
->parent
.tracefiles
,
1526 LttvTracefileContext
*, i
));
1527 type
= lttv_attribute_get(tracefiles_tree
, i
, &name
, &value
, &is_named
);
1528 g_assert(type
== LTTV_GOBJECT
);
1529 tracefile_tree
= *((LttvAttribute
**)(value
.v_gobject
));
1531 type
= lttv_attribute_get_by_name(tracefile_tree
, LTTV_STATE_EVENT
,
1533 g_assert(type
== LTTV_POINTER
);
1534 if(*(value
.v_pointer
) != NULL
) g_free(*(value
.v_pointer
));
1536 g_object_unref(G_OBJECT(tracefiles_tree
));
1540 static void free_saved_state(LttvTraceState
*self
)
1544 LttvAttributeType type
;
1546 LttvAttributeValue value
;
1548 LttvAttributeName name
;
1552 LttvAttribute
*saved_states
;
1554 saved_states
= lttv_attribute_find_subdir(self
->parent
.t_a
,
1555 LTTV_STATE_SAVED_STATES
);
1557 nb
= lttv_attribute_get_number(saved_states
);
1558 for(i
= 0 ; i
< nb
; i
++) {
1559 type
= lttv_attribute_get(saved_states
, i
, &name
, &value
, &is_named
);
1560 g_assert(type
== LTTV_GOBJECT
);
1561 state_saved_free(self
, *((LttvAttribute
**)value
.v_gobject
));
1564 lttv_attribute_remove_by_name(self
->parent
.t_a
, LTTV_STATE_SAVED_STATES
);
1569 create_max_time(LttvTraceState
*tcs
)
1571 LttvAttributeValue v
;
1573 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
1575 g_assert(*(v
.v_pointer
) == NULL
);
1576 *(v
.v_pointer
) = g_new(LttTime
,1);
1577 *((LttTime
*)*(v
.v_pointer
)) = ltt_time_zero
;
1582 get_max_time(LttvTraceState
*tcs
)
1584 LttvAttributeValue v
;
1586 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
1588 g_assert(*(v
.v_pointer
) != NULL
);
1589 tcs
->max_time_state_recomputed_in_seek
= (LttTime
*)*(v
.v_pointer
);
1594 free_max_time(LttvTraceState
*tcs
)
1596 LttvAttributeValue v
;
1598 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_SAVED_STATES_TIME
,
1600 g_free(*(v
.v_pointer
));
1601 *(v
.v_pointer
) = NULL
;
1605 typedef struct _LttvNameTables
{
1606 // FIXME GQuark *eventtype_names;
1607 GQuark
*syscall_names
;
1613 GQuark
*soft_irq_names
;
1619 create_name_tables(LttvTraceState
*tcs
)
1623 GQuark f_name
, e_name
;
1627 LttvTraceHookByFacility
*thf
;
1633 GString
*fe_name
= g_string_new("");
1635 LttvNameTables
*name_tables
= g_new(LttvNameTables
, 1);
1637 LttvAttributeValue v
;
1639 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_NAME_TABLES
,
1641 g_assert(*(v
.v_pointer
) == NULL
);
1642 *(v
.v_pointer
) = name_tables
;
1643 #if 0 // Use iteration over the facilities_by_name and then list all event
1644 // types of each facility
1645 nb
= ltt_trace_eventtype_number(tcs
->parent
.t
);
1646 name_tables
->eventtype_names
= g_new(GQuark
, nb
);
1647 for(i
= 0 ; i
< nb
; i
++) {
1648 et
= ltt_trace_eventtype_get(tcs
->parent
.t
, i
);
1649 e_name
= ltt_eventtype_name(et
);
1650 f_name
= ltt_facility_name(ltt_eventtype_facility(et
));
1651 g_string_printf(fe_name
, "%s.%s", f_name
, e_name
);
1652 name_tables
->eventtype_names
[i
] = g_quark_from_string(fe_name
->str
);
1655 if(!lttv_trace_find_hook(tcs
->parent
.t
,
1656 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_SYSCALL_ENTRY
,
1657 LTT_FIELD_SYSCALL_ID
, 0, 0,
1660 thf
= lttv_trace_hook_get_first(&h
);
1662 t
= ltt_field_type(thf
->f1
);
1663 nb
= ltt_type_element_number(t
);
1665 lttv_trace_hook_destroy(&h
);
1667 name_tables
->syscall_names
= g_new(GQuark
, nb
);
1668 name_tables
->nb_syscalls
= nb
;
1670 for(i
= 0 ; i
< nb
; i
++) {
1671 name_tables
->syscall_names
[i
] = ltt_enum_string_get(t
, i
);
1672 if(!name_tables
->syscall_names
[i
]) {
1673 GString
*string
= g_string_new("");
1674 g_string_printf(string
, "syscall %u", i
);
1675 name_tables
->syscall_names
[i
] = g_quark_from_string(string
->str
);
1676 g_string_free(string
, TRUE
);
1680 //name_tables->syscall_names = g_new(GQuark, 256);
1681 //for(i = 0 ; i < 256 ; i++) {
1682 // g_string_printf(fe_name, "syscall %d", i);
1683 // name_tables->syscall_names[i] = g_quark_from_string(fe_name->str);
1686 name_tables
->syscall_names
= NULL
;
1687 name_tables
->nb_syscalls
= 0;
1690 if(!lttv_trace_find_hook(tcs
->parent
.t
, LTT_FACILITY_KERNEL_ARCH
,
1691 LTT_EVENT_TRAP_ENTRY
,
1692 LTT_FIELD_TRAP_ID
, 0, 0,
1695 thf
= lttv_trace_hook_get_first(&h
);
1697 t
= ltt_field_type(thf
->f1
);
1698 //nb = ltt_type_element_number(t);
1700 lttv_trace_hook_destroy(&h
);
1703 name_tables->trap_names = g_new(GQuark, nb);
1704 for(i = 0 ; i < nb ; i++) {
1705 name_tables->trap_names[i] = g_quark_from_string(
1706 ltt_enum_string_get(t, i));
1709 name_tables
->nb_traps
= 256;
1710 name_tables
->trap_names
= g_new(GQuark
, 256);
1711 for(i
= 0 ; i
< 256 ; i
++) {
1712 g_string_printf(fe_name
, "trap %d", i
);
1713 name_tables
->trap_names
[i
] = g_quark_from_string(fe_name
->str
);
1716 name_tables
->trap_names
= NULL
;
1717 name_tables
->nb_traps
= 0;
1720 if(!lttv_trace_find_hook(tcs
->parent
.t
,
1721 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_ENTRY
,
1722 LTT_FIELD_IRQ_ID
, 0, 0,
1725 thf
= lttv_trace_hook_get_first(&h
);
1727 t
= ltt_field_type(thf
->f1
);
1728 //nb = ltt_type_element_number(t);
1730 lttv_trace_hook_destroy(&h
);
1733 name_tables->irq_names = g_new(GQuark, nb);
1734 for(i = 0 ; i < nb ; i++) {
1735 name_tables->irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
1739 name_tables
->nb_irqs
= 256;
1740 name_tables
->irq_names
= g_new(GQuark
, 256);
1741 for(i
= 0 ; i
< 256 ; i
++) {
1742 g_string_printf(fe_name
, "irq %d", i
);
1743 name_tables
->irq_names
[i
] = g_quark_from_string(fe_name
->str
);
1746 name_tables
->nb_irqs
= 0;
1747 name_tables
->irq_names
= NULL
;
1750 name_tables->soft_irq_names = g_new(GQuark, nb);
1751 for(i = 0 ; i < nb ; i++) {
1752 name_tables->soft_irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
1756 name_tables
->nb_softirqs
= 256;
1757 name_tables
->soft_irq_names
= g_new(GQuark
, 256);
1758 for(i
= 0 ; i
< 256 ; i
++) {
1759 g_string_printf(fe_name
, "softirq %d", i
);
1760 name_tables
->soft_irq_names
[i
] = g_quark_from_string(fe_name
->str
);
1764 g_string_free(fe_name
, TRUE
);
1769 get_name_tables(LttvTraceState
*tcs
)
1771 LttvNameTables
*name_tables
;
1773 LttvAttributeValue v
;
1775 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_NAME_TABLES
,
1777 g_assert(*(v
.v_pointer
) != NULL
);
1778 name_tables
= (LttvNameTables
*)*(v
.v_pointer
);
1779 //tcs->eventtype_names = name_tables->eventtype_names;
1780 tcs
->syscall_names
= name_tables
->syscall_names
;
1781 tcs
->nb_syscalls
= name_tables
->nb_syscalls
;
1782 tcs
->trap_names
= name_tables
->trap_names
;
1783 tcs
->nb_traps
= name_tables
->nb_traps
;
1784 tcs
->irq_names
= name_tables
->irq_names
;
1785 tcs
->soft_irq_names
= name_tables
->soft_irq_names
;
1786 tcs
->nb_irqs
= name_tables
->nb_irqs
;
1787 tcs
->nb_softirqs
= name_tables
->nb_softirqs
;
1792 free_name_tables(LttvTraceState
*tcs
)
1794 LttvNameTables
*name_tables
;
1796 LttvAttributeValue v
;
1798 lttv_attribute_find(tcs
->parent
.t_a
, LTTV_STATE_NAME_TABLES
,
1800 name_tables
= (LttvNameTables
*)*(v
.v_pointer
);
1801 *(v
.v_pointer
) = NULL
;
1803 // g_free(name_tables->eventtype_names);
1804 if(name_tables
->syscall_names
) g_free(name_tables
->syscall_names
);
1805 if(name_tables
->trap_names
) g_free(name_tables
->trap_names
);
1806 if(name_tables
->irq_names
) g_free(name_tables
->irq_names
);
1807 if(name_tables
->soft_irq_names
) g_free(name_tables
->soft_irq_names
);
1808 if(name_tables
) g_free(name_tables
);
1811 #ifdef HASH_TABLE_DEBUG
1813 static void test_process(gpointer key
, gpointer value
, gpointer user_data
)
1815 LttvProcessState
*process
= (LttvProcessState
*)value
;
1817 /* Test for process corruption */
1818 guint stack_len
= process
->execution_stack
->len
;
1821 static void hash_table_check(GHashTable
*table
)
1823 g_hash_table_foreach(table
, test_process
, NULL
);
1829 /* clears the stack and sets the state passed as argument */
1830 static void cpu_set_base_mode(LttvCPUState
*cpust
, LttvCPUMode state
)
1832 g_array_set_size(cpust
->mode_stack
, 1);
1833 ((GQuark
*)cpust
->mode_stack
->data
)[0] = state
;
1836 static void cpu_push_mode(LttvCPUState
*cpust
, LttvCPUMode state
)
1838 g_array_set_size(cpust
->mode_stack
, cpust
->mode_stack
->len
+ 1);
1839 ((GQuark
*)cpust
->mode_stack
->data
)[cpust
->mode_stack
->len
- 1] = state
;
1842 static void cpu_pop_mode(LttvCPUState
*cpust
)
1844 if(cpust
->mode_stack
->len
<= 1)
1845 cpu_set_base_mode(cpust
, LTTV_CPU_UNKNOWN
);
1847 g_array_set_size(cpust
->mode_stack
, cpust
->mode_stack
->len
- 1);
1850 /* clears the stack and sets the state passed as argument */
1851 static void bdev_set_base_mode(LttvBdevState
*bdevst
, LttvBdevMode state
)
1853 g_array_set_size(bdevst
->mode_stack
, 1);
1854 ((GQuark
*)bdevst
->mode_stack
->data
)[0] = state
;
1857 static void bdev_push_mode(LttvBdevState
*bdevst
, LttvBdevMode state
)
1859 g_array_set_size(bdevst
->mode_stack
, bdevst
->mode_stack
->len
+ 1);
1860 ((GQuark
*)bdevst
->mode_stack
->data
)[bdevst
->mode_stack
->len
- 1] = state
;
1863 static void bdev_pop_mode(LttvBdevState
*bdevst
)
1865 if(bdevst
->mode_stack
->len
<= 1)
1866 bdev_set_base_mode(bdevst
, LTTV_BDEV_UNKNOWN
);
1868 g_array_set_size(bdevst
->mode_stack
, bdevst
->mode_stack
->len
- 1);
1871 static void irq_set_base_mode(LttvIRQState
*irqst
, LttvIRQMode state
)
1873 g_array_set_size(irqst
->mode_stack
, 1);
1874 ((GQuark
*)irqst
->mode_stack
->data
)[0] = state
;
1877 static void irq_push_mode(LttvIRQState
*irqst
, LttvIRQMode state
)
1879 g_array_set_size(irqst
->mode_stack
, irqst
->mode_stack
->len
+ 1);
1880 ((GQuark
*)irqst
->mode_stack
->data
)[irqst
->mode_stack
->len
- 1] = state
;
1883 static void irq_pop_mode(LttvIRQState
*irqst
)
1885 if(irqst
->mode_stack
->len
<= 1)
1886 irq_set_base_mode(irqst
, LTTV_IRQ_UNKNOWN
);
1888 g_array_set_size(irqst
->mode_stack
, irqst
->mode_stack
->len
- 1);
1891 static void push_state(LttvTracefileState
*tfs
, LttvExecutionMode t
,
1894 LttvExecutionState
*es
;
1896 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
1897 guint cpu
= tfs
->cpu
;
1899 #ifdef HASH_TABLE_DEBUG
1900 hash_table_check(ts
->processes
);
1902 LttvProcessState
*process
= ts
->running_process
[cpu
];
1904 guint depth
= process
->execution_stack
->len
;
1906 process
->execution_stack
=
1907 g_array_set_size(process
->execution_stack
, depth
+ 1);
1910 &g_array_index(process
->execution_stack
, LttvExecutionState
, depth
- 1);
1912 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, depth
);
1915 es
->entry
= es
->change
= tfs
->parent
.timestamp
;
1916 es
->cum_cpu_time
= ltt_time_zero
;
1917 es
->s
= process
->state
->s
;
1918 process
->state
= es
;
1922 * return 1 when empty, else 0 */
1923 int lttv_state_pop_state_cleanup(LttvProcessState
*process
,
1924 LttvTracefileState
*tfs
)
1926 guint cpu
= tfs
->cpu
;
1927 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
1929 guint depth
= process
->execution_stack
->len
;
1935 process
->execution_stack
=
1936 g_array_set_size(process
->execution_stack
, depth
- 1);
1937 process
->state
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
1939 process
->state
->change
= tfs
->parent
.timestamp
;
1944 static void pop_state(LttvTracefileState
*tfs
, LttvExecutionMode t
)
1946 guint cpu
= tfs
->cpu
;
1947 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
1948 LttvProcessState
*process
= ts
->running_process
[cpu
];
1950 guint depth
= process
->execution_stack
->len
;
1952 if(process
->state
->t
!= t
){
1953 g_info("Different execution mode type (%lu.%09lu): ignore it\n",
1954 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
1955 g_info("process state has %s when pop_int is %s\n",
1956 g_quark_to_string(process
->state
->t
),
1957 g_quark_to_string(t
));
1958 g_info("{ %u, %u, %s, %s, %s }\n",
1961 g_quark_to_string(process
->name
),
1962 g_quark_to_string(process
->brand
),
1963 g_quark_to_string(process
->state
->s
));
1968 g_info("Trying to pop last state on stack (%lu.%09lu): ignore it\n",
1969 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
1973 process
->execution_stack
=
1974 g_array_set_size(process
->execution_stack
, depth
- 1);
1975 process
->state
= &g_array_index(process
->execution_stack
, LttvExecutionState
,
1977 process
->state
->change
= tfs
->parent
.timestamp
;
1980 struct search_result
{
1981 const LttTime
*time
; /* Requested time */
1982 LttTime
*best
; /* Best result */
1985 static gint
search_usertrace(gconstpointer a
, gconstpointer b
)
1987 const LttTime
*elem_time
= (const LttTime
*)a
;
1988 /* Explicit non const cast */
1989 struct search_result
*res
= (struct search_result
*)b
;
1991 if(ltt_time_compare(*elem_time
, *(res
->time
)) < 0) {
1992 /* The usertrace was created before the schedchange */
1993 /* Get larger keys */
1995 } else if(ltt_time_compare(*elem_time
, *(res
->time
)) >= 0) {
1996 /* The usertrace was created after the schedchange time */
1997 /* Get smaller keys */
1999 if(ltt_time_compare(*elem_time
, *res
->best
) < 0) {
2000 res
->best
= elem_time
;
2003 res
->best
= elem_time
;
2010 static LttvTracefileState
*ltt_state_usertrace_find(LttvTraceState
*tcs
,
2011 guint pid
, const LttTime
*timestamp
)
2013 LttvTracefileState
*tfs
= NULL
;
2014 struct search_result res
;
2015 /* Find the usertrace associated with a pid and time interval.
2016 * Search in the usertraces by PID (within a hash) and then, for each
2017 * corresponding element of the array, find the first one with creation
2018 * timestamp the lowest, but higher or equal to "timestamp". */
2019 res
.time
= timestamp
;
2021 GTree
*usertrace_tree
= g_hash_table_lookup(tcs
->usertraces
, (gpointer
)pid
);
2022 if(usertrace_tree
) {
2023 g_tree_search(usertrace_tree
, search_usertrace
, &res
);
2025 tfs
= g_tree_lookup(usertrace_tree
, res
.best
);
2033 lttv_state_create_process(LttvTraceState
*tcs
, LttvProcessState
*parent
,
2034 guint cpu
, guint pid
, guint tgid
, GQuark name
, const LttTime
*timestamp
)
2036 LttvProcessState
*process
= g_new(LttvProcessState
, 1);
2038 LttvExecutionState
*es
;
2040 LttvTraceContext
*tc
= (LttvTraceContext
*)tcs
;
2045 process
->tgid
= tgid
;
2047 process
->name
= name
;
2048 process
->brand
= LTTV_STATE_UNBRANDED
;
2049 //process->last_cpu = tfs->cpu_name;
2050 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
2051 process
->type
= LTTV_STATE_USER_THREAD
;
2052 process
->usertrace
= ltt_state_usertrace_find(tcs
, pid
, timestamp
);
2053 process
->current_function
= 0; //function 0x0 by default.
2055 g_info("Process %u, core %p", process
->pid
, process
);
2056 g_hash_table_insert(tcs
->processes
, process
, process
);
2059 process
->ppid
= parent
->pid
;
2060 process
->creation_time
= *timestamp
;
2063 /* No parent. This process exists but we are missing all information about
2064 its creation. The birth time is set to zero but we remember the time of
2069 process
->creation_time
= ltt_time_zero
;
2072 process
->insertion_time
= *timestamp
;
2073 sprintf(buffer
,"%d-%lu.%lu",pid
, process
->creation_time
.tv_sec
,
2074 process
->creation_time
.tv_nsec
);
2075 process
->pid_time
= g_quark_from_string(buffer
);
2077 //process->last_cpu = tfs->cpu_name;
2078 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
2079 process
->execution_stack
= g_array_sized_new(FALSE
, FALSE
,
2080 sizeof(LttvExecutionState
), PREALLOCATED_EXECUTION_STACK
);
2081 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 2);
2082 es
= process
->state
= &g_array_index(process
->execution_stack
,
2083 LttvExecutionState
, 0);
2084 es
->t
= LTTV_STATE_USER_MODE
;
2085 es
->n
= LTTV_STATE_SUBMODE_NONE
;
2086 es
->entry
= *timestamp
;
2087 //g_assert(timestamp->tv_sec != 0);
2088 es
->change
= *timestamp
;
2089 es
->cum_cpu_time
= ltt_time_zero
;
2090 es
->s
= LTTV_STATE_RUN
;
2092 es
= process
->state
= &g_array_index(process
->execution_stack
,
2093 LttvExecutionState
, 1);
2094 es
->t
= LTTV_STATE_SYSCALL
;
2095 es
->n
= LTTV_STATE_SUBMODE_NONE
;
2096 es
->entry
= *timestamp
;
2097 //g_assert(timestamp->tv_sec != 0);
2098 es
->change
= *timestamp
;
2099 es
->cum_cpu_time
= ltt_time_zero
;
2100 es
->s
= LTTV_STATE_WAIT_FORK
;
2102 /* Allocate an empty function call stack. If it's empty, use 0x0. */
2103 process
->user_stack
= g_array_sized_new(FALSE
, FALSE
,
2104 sizeof(guint64
), 0);
2109 LttvProcessState
*lttv_state_find_process(LttvTraceState
*ts
, guint cpu
,
2112 LttvProcessState key
;
2113 LttvProcessState
*process
;
2117 process
= g_hash_table_lookup(ts
->processes
, &key
);
2122 lttv_state_find_process_or_create(LttvTraceState
*ts
, guint cpu
, guint pid
,
2123 const LttTime
*timestamp
)
2125 LttvProcessState
*process
= lttv_state_find_process(ts
, cpu
, pid
);
2126 LttvExecutionState
*es
;
2128 /* Put ltt_time_zero creation time for unexisting processes */
2129 if(unlikely(process
== NULL
)) {
2130 process
= lttv_state_create_process(ts
,
2131 NULL
, cpu
, pid
, 0, LTTV_STATE_UNNAMED
, timestamp
);
2132 /* We are not sure is it's a kernel thread or normal thread, put the
2133 * bottom stack state to unknown */
2134 process
->execution_stack
=
2135 g_array_set_size(process
->execution_stack
, 1);
2136 process
->state
= es
=
2137 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
2138 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
2139 es
->s
= LTTV_STATE_UNNAMED
;
2144 /* FIXME : this function should be called when we receive an event telling that
2145 * release_task has been called in the kernel. In happens generally when
2146 * the parent waits for its child terminaison, but may also happen in special
2147 * cases in the child's exit : when the parent ignores its children SIGCCHLD or
2148 * has the flag SA_NOCLDWAIT. It can also happen when the child is part
2149 * of a killed thread ground, but isn't the leader.
2151 static void exit_process(LttvTracefileState
*tfs
, LttvProcessState
*process
)
2153 LttvTraceState
*ts
= LTTV_TRACE_STATE(tfs
->parent
.t_context
);
2154 LttvProcessState key
;
2156 key
.pid
= process
->pid
;
2157 key
.cpu
= process
->cpu
;
2158 g_hash_table_remove(ts
->processes
, &key
);
2159 g_array_free(process
->execution_stack
, TRUE
);
2160 g_array_free(process
->user_stack
, TRUE
);
2165 static void free_process_state(gpointer key
, gpointer value
,gpointer user_data
)
2167 g_array_free(((LttvProcessState
*)value
)->execution_stack
, TRUE
);
2168 g_array_free(((LttvProcessState
*)value
)->user_stack
, TRUE
);
2173 static void lttv_state_free_process_table(GHashTable
*processes
)
2175 g_hash_table_foreach(processes
, free_process_state
, NULL
);
2176 g_hash_table_destroy(processes
);
2180 static gboolean
syscall_entry(void *hook_data
, void *call_data
)
2182 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2184 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2185 LttvProcessState
*process
= ts
->running_process
[cpu
];
2186 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2187 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2188 LttField
*f
= thf
->f1
;
2190 LttvExecutionSubmode submode
;
2192 guint nb_syscalls
= ((LttvTraceState
*)(s
->parent
.t_context
))->nb_syscalls
;
2193 guint syscall
= ltt_event_get_unsigned(e
, f
);
2195 if(syscall
< nb_syscalls
) {
2196 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->syscall_names
[
2199 /* Fixup an incomplete syscall table */
2200 GString
*string
= g_string_new("");
2201 g_string_printf(string
, "syscall %u", syscall
);
2202 submode
= g_quark_from_string(string
->str
);
2203 g_string_free(string
, TRUE
);
2205 /* There can be no system call from PID 0 : unknown state */
2206 if(process
->pid
!= 0)
2207 push_state(s
, LTTV_STATE_SYSCALL
, submode
);
2212 static gboolean
syscall_exit(void *hook_data
, void *call_data
)
2214 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2216 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2217 LttvProcessState
*process
= ts
->running_process
[cpu
];
2219 /* There can be no system call from PID 0 : unknown state */
2220 if(process
->pid
!= 0)
2221 pop_state(s
, LTTV_STATE_SYSCALL
);
2226 static gboolean
trap_entry(void *hook_data
, void *call_data
)
2228 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2229 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2230 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2231 LttField
*f
= thf
->f1
;
2233 LttvExecutionSubmode submode
;
2235 guint64 nb_traps
= ((LttvTraceState
*)(s
->parent
.t_context
))->nb_traps
;
2236 guint64 trap
= ltt_event_get_long_unsigned(e
, f
);
2238 if(trap
< nb_traps
) {
2239 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->trap_names
[trap
];
2241 /* Fixup an incomplete trap table */
2242 GString
*string
= g_string_new("");
2243 g_string_printf(string
, "trap %llu", trap
);
2244 submode
= g_quark_from_string(string
->str
);
2245 g_string_free(string
, TRUE
);
2248 push_state(s
, LTTV_STATE_TRAP
, submode
);
2250 /* update cpu status */
2251 cpu_push_mode(s
->cpu_state
, LTTV_CPU_TRAP
);
2256 static gboolean
trap_exit(void *hook_data
, void *call_data
)
2258 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2260 pop_state(s
, LTTV_STATE_TRAP
);
2262 /* update cpu status */
2263 cpu_pop_mode(s
->cpu_state
);
2268 static gboolean
irq_entry(void *hook_data
, void *call_data
)
2270 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2271 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2272 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2273 guint8 fac_id
= ltt_event_facility_id(e
);
2274 guint8 ev_id
= ltt_event_eventtype_id(e
);
2275 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2276 // g_assert(lttv_trace_hook_get_first((LttvTraceHook *)hook_data)->f1 != NULL);
2277 g_assert(thf
->f1
!= NULL
);
2278 // g_assert(thf == lttv_trace_hook_get_first((LttvTraceHook *)hook_data));
2279 LttField
*f
= thf
->f1
;
2281 LttvExecutionSubmode submode
;
2282 guint64 irq
= ltt_event_get_long_unsigned(e
, f
);
2283 guint64 nb_irqs
= ((LttvTraceState
*)(s
->parent
.t_context
))->nb_irqs
;
2287 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->irq_names
[irq
];
2289 /* Fixup an incomplete irq table */
2290 GString
*string
= g_string_new("");
2291 g_string_printf(string
, "irq %llu", irq
);
2292 submode
= g_quark_from_string(string
->str
);
2293 g_string_free(string
, TRUE
);
2296 /* Do something with the info about being in user or system mode when int? */
2297 push_state(s
, LTTV_STATE_IRQ
, submode
);
2299 /* update cpu status */
2300 cpu_push_mode(s
->cpu_state
, LTTV_CPU_IRQ
);
2302 /* update irq status */
2303 s
->cpu_state
->last_irq
= irq
;
2304 irq_push_mode(&ts
->irq_states
[irq
], LTTV_IRQ_BUSY
);
2309 static gboolean
soft_irq_exit(void *hook_data
, void *call_data
)
2311 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2313 pop_state(s
, LTTV_STATE_SOFT_IRQ
);
2319 static gboolean
irq_exit(void *hook_data
, void *call_data
)
2321 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2322 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2324 pop_state(s
, LTTV_STATE_IRQ
);
2326 /* update cpu status */
2327 cpu_pop_mode(s
->cpu_state
);
2329 /* update irq status */
2330 irq_pop_mode(&ts
->irq_states
[s
->cpu_state
->last_irq
]);
2335 static gboolean
soft_irq_entry(void *hook_data
, void *call_data
)
2337 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2338 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2339 guint8 fac_id
= ltt_event_facility_id(e
);
2340 guint8 ev_id
= ltt_event_eventtype_id(e
);
2341 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2342 // g_assert(lttv_trace_hook_get_first((LttvTraceHook *)hook_data)->f1 != NULL);
2343 g_assert(thf
->f1
!= NULL
);
2344 // g_assert(thf == lttv_trace_hook_get_first((LttvTraceHook *)hook_data));
2345 LttField
*f
= thf
->f1
;
2347 LttvExecutionSubmode submode
;
2348 guint64 softirq
= ltt_event_get_long_unsigned(e
, f
);
2349 guint64 nb_softirqs
= ((LttvTraceState
*)(s
->parent
.t_context
))->nb_softirqs
;
2352 if(softirq
< nb_softirqs
) {
2353 submode
= ((LttvTraceState
*)(s
->parent
.t_context
))->soft_irq_names
[softirq
];
2355 /* Fixup an incomplete irq table */
2356 GString
*string
= g_string_new("");
2357 g_string_printf(string
, "softirq %llu", softirq
);
2358 submode
= g_quark_from_string(string
->str
);
2359 g_string_free(string
, TRUE
);
2362 /* Do something with the info about being in user or system mode when int? */
2363 push_state(s
, LTTV_STATE_SOFT_IRQ
, submode
);
2367 static gboolean
bdev_request_issue(void *hook_data
, void *call_data
)
2369 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2370 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2371 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2372 guint8 fac_id
= ltt_event_facility_id(e
);
2373 guint8 ev_id
= ltt_event_eventtype_id(e
);
2374 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2376 guint major
= ltt_event_get_long_unsigned(e
, thf
->f1
);
2377 guint minor
= ltt_event_get_long_unsigned(e
, thf
->f2
);
2378 guint oper
= ltt_event_get_long_unsigned(e
, thf
->f3
);
2379 guint16 devcode
= MKDEV(major
,minor
);
2381 /* have we seen this block device before? */
2382 gpointer bdev
= get_hashed_bdevstate(ts
, devcode
);
2385 bdev_push_mode(bdev
, LTTV_BDEV_BUSY_READING
);
2387 bdev_push_mode(bdev
, LTTV_BDEV_BUSY_WRITING
);
2392 static gboolean
bdev_request_complete(void *hook_data
, void *call_data
)
2394 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2395 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2396 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2397 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2399 guint major
= ltt_event_get_long_unsigned(e
, thf
->f1
);
2400 guint minor
= ltt_event_get_long_unsigned(e
, thf
->f2
);
2401 guint oper
= ltt_event_get_long_unsigned(e
, thf
->f3
);
2402 guint16 devcode
= MKDEV(major
,minor
);
2404 /* have we seen this block device before? */
2405 gpointer bdev
= get_hashed_bdevstate(ts
, devcode
);
2407 /* update block device */
2408 bdev_pop_mode(bdev
);
2413 static void push_function(LttvTracefileState
*tfs
, guint64 funcptr
)
2417 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
2418 guint cpu
= tfs
->cpu
;
2419 LttvProcessState
*process
= ts
->running_process
[cpu
];
2421 guint depth
= process
->user_stack
->len
;
2423 process
->user_stack
=
2424 g_array_set_size(process
->user_stack
, depth
+ 1);
2426 new_func
= &g_array_index(process
->user_stack
, guint64
, depth
);
2427 *new_func
= funcptr
;
2428 process
->current_function
= funcptr
;
2431 static void pop_function(LttvTracefileState
*tfs
, guint64 funcptr
)
2433 guint cpu
= tfs
->cpu
;
2434 LttvTraceState
*ts
= (LttvTraceState
*)tfs
->parent
.t_context
;
2435 LttvProcessState
*process
= ts
->running_process
[cpu
];
2437 if(process
->current_function
!= funcptr
){
2438 g_info("Different functions (%lu.%09lu): ignore it\n",
2439 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
2440 g_info("process state has %llu when pop_function is %llu\n",
2441 process
->current_function
, funcptr
);
2442 g_info("{ %u, %u, %s, %s, %s }\n",
2445 g_quark_to_string(process
->name
),
2446 g_quark_to_string(process
->brand
),
2447 g_quark_to_string(process
->state
->s
));
2450 guint depth
= process
->user_stack
->len
;
2453 g_info("Trying to pop last function on stack (%lu.%09lu): ignore it\n",
2454 tfs
->parent
.timestamp
.tv_sec
, tfs
->parent
.timestamp
.tv_nsec
);
2458 process
->user_stack
=
2459 g_array_set_size(process
->user_stack
, depth
- 1);
2460 process
->current_function
=
2461 g_array_index(process
->user_stack
, guint64
, depth
- 2);
2465 static gboolean
function_entry(void *hook_data
, void *call_data
)
2467 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2468 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2469 guint8 fac_id
= ltt_event_facility_id(e
);
2470 guint8 ev_id
= ltt_event_eventtype_id(e
);
2471 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2472 g_assert(thf
->f1
!= NULL
);
2473 LttField
*f
= thf
->f1
;
2474 guint64 funcptr
= ltt_event_get_long_unsigned(e
, f
);
2476 push_function(s
, funcptr
);
2480 static gboolean
function_exit(void *hook_data
, void *call_data
)
2482 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2483 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2484 guint8 fac_id
= ltt_event_facility_id(e
);
2485 guint8 ev_id
= ltt_event_eventtype_id(e
);
2486 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2487 g_assert(thf
->f1
!= NULL
);
2488 LttField
*f
= thf
->f1
;
2489 guint64 funcptr
= ltt_event_get_long_unsigned(e
, f
);
2491 LttvExecutionSubmode submode
;
2493 pop_function(s
, funcptr
);
2497 static gboolean
schedchange(void *hook_data
, void *call_data
)
2499 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2501 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2502 LttvProcessState
*process
= ts
->running_process
[cpu
];
2503 LttvProcessState
*old_process
= ts
->running_process
[cpu
];
2505 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2506 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2507 guint pid_in
, pid_out
;
2510 pid_out
= ltt_event_get_unsigned(e
, thf
->f1
);
2511 pid_in
= ltt_event_get_unsigned(e
, thf
->f2
);
2512 state_out
= ltt_event_get_long_int(e
, thf
->f3
);
2514 if(likely(process
!= NULL
)) {
2516 /* We could not know but it was not the idle process executing.
2517 This should only happen at the beginning, before the first schedule
2518 event, and when the initial information (current process for each CPU)
2519 is missing. It is not obvious how we could, after the fact, compensate
2520 the wrongly attributed statistics. */
2522 //This test only makes sense once the state is known and if there is no
2523 //missing events. We need to silently ignore schedchange coming after a
2524 //process_free, or it causes glitches. (FIXME)
2525 //if(unlikely(process->pid != pid_out)) {
2526 // g_assert(process->pid == 0);
2528 if(process
->pid
== 0
2529 && process
->state
->t
== LTTV_STATE_MODE_UNKNOWN
) {
2531 /* Scheduling out of pid 0 at beginning of the trace :
2532 * we know for sure it is in syscall mode at this point. */
2533 g_assert(process
->execution_stack
->len
== 1);
2534 process
->state
->t
= LTTV_STATE_SYSCALL
;
2535 process
->state
->s
= LTTV_STATE_WAIT
;
2536 process
->state
->change
= s
->parent
.timestamp
;
2537 process
->state
->entry
= s
->parent
.timestamp
;
2540 if(unlikely(process
->state
->s
== LTTV_STATE_EXIT
)) {
2541 process
->state
->s
= LTTV_STATE_ZOMBIE
;
2542 process
->state
->change
= s
->parent
.timestamp
;
2544 if(unlikely(state_out
== 0)) process
->state
->s
= LTTV_STATE_WAIT_CPU
;
2545 else process
->state
->s
= LTTV_STATE_WAIT
;
2546 process
->state
->change
= s
->parent
.timestamp
;
2549 if(state_out
== 32 || state_out
== 128)
2550 exit_process(s
, process
); /* EXIT_DEAD || TASK_DEAD */
2551 /* see sched.h for states */
2554 process
= ts
->running_process
[cpu
] =
2555 lttv_state_find_process_or_create(
2556 (LttvTraceState
*)s
->parent
.t_context
,
2558 &s
->parent
.timestamp
);
2559 process
->state
->s
= LTTV_STATE_RUN
;
2561 if(process
->usertrace
)
2562 process
->usertrace
->cpu
= cpu
;
2563 // process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)s)->tf);
2564 process
->state
->change
= s
->parent
.timestamp
;
2566 /* update cpu status */
2568 cpu_set_base_mode(s
->cpu_state
, LTTV_CPU_IDLE
);
2570 cpu_set_base_mode(s
->cpu_state
, LTTV_CPU_BUSY
);
2575 static gboolean
process_fork(void *hook_data
, void *call_data
)
2577 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2578 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2579 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2581 guint child_pid
; /* In the Linux Kernel, there is one PID per thread. */
2582 guint child_tgid
; /* tgid in the Linux kernel is the "real" POSIX PID. */
2583 LttvProcessState
*zombie_process
;
2585 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2586 LttvProcessState
*process
= ts
->running_process
[cpu
];
2587 LttvProcessState
*child_process
;
2590 parent_pid
= ltt_event_get_unsigned(e
, thf
->f1
);
2593 child_pid
= ltt_event_get_unsigned(e
, thf
->f2
);
2594 s
->parent
.target_pid
= child_pid
;
2597 if(thf
->f3
) child_tgid
= ltt_event_get_unsigned(e
, thf
->f3
);
2598 else child_tgid
= 0;
2600 /* Mathieu : it seems like the process might have been scheduled in before the
2601 * fork, and, in a rare case, might be the current process. This might happen
2602 * in a SMP case where we don't have enough precision on the clocks.
2604 * Test reenabled after precision fixes on time. (Mathieu) */
2606 zombie_process
= lttv_state_find_process(ts
, ANY_CPU
, child_pid
);
2608 if(unlikely(zombie_process
!= NULL
)) {
2609 /* Reutilisation of PID. Only now we are sure that the old PID
2610 * has been released. FIXME : should know when release_task happens instead.
2612 guint num_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
2614 for(i
=0; i
< num_cpus
; i
++) {
2615 g_assert(zombie_process
!= ts
->running_process
[i
]);
2618 exit_process(s
, zombie_process
);
2621 g_assert(process
->pid
!= child_pid
);
2622 // FIXME : Add this test in the "known state" section
2623 // g_assert(process->pid == parent_pid);
2624 child_process
= lttv_state_find_process(ts
, ANY_CPU
, child_pid
);
2625 if(child_process
== NULL
) {
2626 child_process
= lttv_state_create_process(ts
, process
, cpu
,
2627 child_pid
, child_tgid
,
2628 LTTV_STATE_UNNAMED
, &s
->parent
.timestamp
);
2630 /* The process has already been created : due to time imprecision between
2631 * multiple CPUs : it has been scheduled in before creation. Note that we
2632 * shouldn't have this kind of imprecision.
2634 * Simply put a correct parent.
2636 g_assert(0); /* This is a problematic case : the process has been created
2637 before the fork event */
2638 child_process
->ppid
= process
->pid
;
2639 child_process
->tgid
= child_tgid
;
2641 g_assert(child_process
->name
== LTTV_STATE_UNNAMED
);
2642 child_process
->name
= process
->name
;
2643 child_process
->brand
= process
->brand
;
2648 /* We stamp a newly created process as kernel_thread.
2649 * The thread should not be running yet. */
2650 static gboolean
process_kernel_thread(void *hook_data
, void *call_data
)
2652 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2653 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2654 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2657 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2658 LttvProcessState
*process
;
2659 LttvExecutionState
*es
;
2662 pid
= (guint
)ltt_event_get_long_unsigned(e
, thf
->f1
);
2663 s
->parent
.target_pid
= pid
;
2665 process
= lttv_state_find_process_or_create(ts
, ANY_CPU
, pid
,
2667 process
->execution_stack
=
2668 g_array_set_size(process
->execution_stack
, 1);
2669 es
= process
->state
=
2670 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
2671 es
->t
= LTTV_STATE_SYSCALL
;
2672 process
->type
= LTTV_STATE_KERNEL_THREAD
;
2677 static gboolean
process_exit(void *hook_data
, void *call_data
)
2679 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2680 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2681 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2685 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2686 LttvProcessState
*process
; // = ts->running_process[cpu];
2688 pid
= ltt_event_get_unsigned(e
, thf
->f1
);
2689 s
->parent
.target_pid
= pid
;
2691 // FIXME : Add this test in the "known state" section
2692 // g_assert(process->pid == pid);
2694 process
= lttv_state_find_process(ts
, ANY_CPU
, pid
);
2695 if(likely(process
!= NULL
)) {
2696 process
->state
->s
= LTTV_STATE_EXIT
;
2701 static gboolean
process_free(void *hook_data
, void *call_data
)
2703 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2704 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2705 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2706 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2708 LttvProcessState
*process
;
2710 /* PID of the process to release */
2711 release_pid
= ltt_event_get_unsigned(e
, thf
->f1
);
2712 s
->parent
.target_pid
= release_pid
;
2714 g_assert(release_pid
!= 0);
2716 process
= lttv_state_find_process(ts
, ANY_CPU
, release_pid
);
2718 if(likely(process
!= NULL
)) {
2719 /* release_task is happening at kernel level : we can now safely release
2720 * the data structure of the process */
2721 //This test is fun, though, as it may happen that
2722 //at time t : CPU 0 : process_free
2723 //at time t+150ns : CPU 1 : schedule out
2724 //Clearly due to time imprecision, we disable it. (Mathieu)
2725 //If this weird case happen, we have no choice but to put the
2726 //Currently running process on the cpu to 0.
2727 //I re-enable it following time precision fixes. (Mathieu)
2728 //Well, in the case where an process is freed by a process on another CPU
2729 //and still scheduled, it happens that this is the schedchange that will
2730 //drop the last reference count. Do not free it here!
2731 guint num_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
2733 for(i
=0; i
< num_cpus
; i
++) {
2734 //g_assert(process != ts->running_process[i]);
2735 if(process
== ts
->running_process
[i
]) {
2736 //ts->running_process[i] = lttv_state_find_process(ts, i, 0);
2740 if(i
== num_cpus
) /* process is not scheduled */
2741 exit_process(s
, process
);
2748 static gboolean
process_exec(void *hook_data
, void *call_data
)
2750 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2751 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2752 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2753 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2756 LttvProcessState
*process
= ts
->running_process
[cpu
];
2758 #if 0//how to use a sequence that must be transformed in a string
2759 /* PID of the process to release */
2760 guint64 name_len
= ltt_event_field_element_number(e
, thf
->f1
);
2761 //name = ltt_event_get_string(e, thf->f1);
2762 LttField
*child
= ltt_event_field_element_select(e
, thf
->f1
, 0);
2764 (gchar
*)(ltt_event_data(e
)+ltt_event_field_offset(e
, child
));
2765 gchar
*null_term_name
= g_new(gchar
, name_len
+1);
2766 memcpy(null_term_name
, name_begin
, name_len
);
2767 null_term_name
[name_len
] = '\0';
2768 process
->name
= g_quark_from_string(null_term_name
);
2771 process
->name
= g_quark_from_string(ltt_event_get_string(e
, thf
->f1
));
2772 process
->brand
= LTTV_STATE_UNBRANDED
;
2773 //g_free(null_term_name);
2777 static gboolean
thread_brand(void *hook_data
, void *call_data
)
2779 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2780 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2781 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2782 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2785 LttvProcessState
*process
= ts
->running_process
[cpu
];
2787 name
= ltt_event_get_string(e
, thf
->f1
);
2788 process
->brand
= g_quark_from_string(name
);
2793 static void fix_process(gpointer key
, gpointer value
,
2796 LttvProcessState
*process
;
2797 LttvExecutionState
*es
;
2798 process
= (LttvProcessState
*)value
;
2799 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)user_data
;
2800 LttTime
*timestamp
= (LttTime
*)user_data
;
2802 if(process
->type
== LTTV_STATE_KERNEL_THREAD
) {
2803 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
2804 if(es
->t
== LTTV_STATE_MODE_UNKNOWN
) {
2805 es
->t
= LTTV_STATE_SYSCALL
;
2806 es
->n
= LTTV_STATE_SUBMODE_NONE
;
2807 es
->entry
= *timestamp
;
2808 es
->change
= *timestamp
;
2809 es
->cum_cpu_time
= ltt_time_zero
;
2810 if(es
->s
== LTTV_STATE_UNNAMED
)
2811 es
->s
= LTTV_STATE_WAIT
;
2814 es
= &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
2815 if(es
->t
== LTTV_STATE_MODE_UNKNOWN
) {
2816 es
->t
= LTTV_STATE_USER_MODE
;
2817 es
->n
= LTTV_STATE_SUBMODE_NONE
;
2818 es
->entry
= *timestamp
;
2819 //g_assert(timestamp->tv_sec != 0);
2820 es
->change
= *timestamp
;
2821 es
->cum_cpu_time
= ltt_time_zero
;
2822 if(es
->s
== LTTV_STATE_UNNAMED
)
2823 es
->s
= LTTV_STATE_RUN
;
2825 if(process
->execution_stack
->len
== 1) {
2826 /* Still in bottom unknown mode, means never did a system call
2827 * May be either in user mode, syscall mode, running or waiting.*/
2828 /* FIXME : we may be tagging syscall mode when being user mode */
2829 process
->execution_stack
=
2830 g_array_set_size(process
->execution_stack
, 2);
2831 es
= process
->state
= &g_array_index(process
->execution_stack
,
2832 LttvExecutionState
, 1);
2833 es
->t
= LTTV_STATE_SYSCALL
;
2834 es
->n
= LTTV_STATE_SUBMODE_NONE
;
2835 es
->entry
= *timestamp
;
2836 //g_assert(timestamp->tv_sec != 0);
2837 es
->change
= *timestamp
;
2838 es
->cum_cpu_time
= ltt_time_zero
;
2839 if(es
->s
== LTTV_STATE_WAIT_FORK
)
2840 es
->s
= LTTV_STATE_WAIT
;
2846 static gboolean
statedump_end(void *hook_data
, void *call_data
)
2848 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2849 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2850 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
2851 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2852 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2854 /* For all processes */
2855 /* if kernel thread, if stack[0] is unknown, set to syscall mode, wait */
2856 /* else, if stack[0] is unknown, set to user mode, running */
2858 g_hash_table_foreach(ts
->processes
, fix_process
, &tfc
->timestamp
);
2861 static gboolean
enum_process_state(void *hook_data
, void *call_data
)
2863 LttvTracefileState
*s
= (LttvTracefileState
*)call_data
;
2864 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
2865 //It's slow : optimise later by doing this before reading trace.
2866 LttEventType
*et
= ltt_event_eventtype(e
);
2868 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
2874 LttvTraceState
*ts
= (LttvTraceState
*)s
->parent
.t_context
;
2875 LttvProcessState
*process
= ts
->running_process
[cpu
];
2876 LttvProcessState
*parent_process
;
2877 LttField
*f4
, *f5
, *f6
, *f7
, *f8
;
2878 GQuark type
, mode
, submode
, status
;
2879 LttvExecutionState
*es
;
2883 pid
= ltt_event_get_unsigned(e
, thf
->f1
);
2884 s
->parent
.target_pid
= pid
;
2887 parent_pid
= ltt_event_get_unsigned(e
, thf
->f2
);
2890 command
= ltt_event_get_string(e
, thf
->f3
);
2893 f4
= ltt_eventtype_field_by_name(et
, LTT_FIELD_TYPE
);
2894 type
= ltt_enum_string_get(ltt_field_type(f4
),
2895 ltt_event_get_unsigned(e
, f4
));
2898 f5
= ltt_eventtype_field_by_name(et
, LTT_FIELD_MODE
);
2899 mode
= ltt_enum_string_get(ltt_field_type(f5
),
2900 ltt_event_get_unsigned(e
, f5
));
2903 f6
= ltt_eventtype_field_by_name(et
, LTT_FIELD_SUBMODE
);
2904 submode
= ltt_enum_string_get(ltt_field_type(f6
),
2905 ltt_event_get_unsigned(e
, f6
));
2908 f7
= ltt_eventtype_field_by_name(et
, LTT_FIELD_STATUS
);
2909 status
= ltt_enum_string_get(ltt_field_type(f7
),
2910 ltt_event_get_unsigned(e
, f7
));
2913 f8
= ltt_eventtype_field_by_name(et
, LTT_FIELD_TGID
);
2914 if(f8
) tgid
= ltt_event_get_unsigned(e
, f8
);
2919 nb_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
2920 for(i
=0; i
<nb_cpus
; i
++) {
2921 process
= lttv_state_find_process(ts
, i
, pid
);
2922 g_assert(process
!= NULL
);
2924 process
->ppid
= parent_pid
;
2925 process
->tgid
= tgid
;
2926 process
->name
= g_quark_from_string(command
);
2928 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
2929 process
->type
= LTTV_STATE_KERNEL_THREAD
;
2933 /* The process might exist if a process was forked while performing the
2935 process
= lttv_state_find_process(ts
, ANY_CPU
, pid
);
2936 if(process
== NULL
) {
2937 parent_process
= lttv_state_find_process(ts
, ANY_CPU
, parent_pid
);
2938 process
= lttv_state_create_process(ts
, parent_process
, cpu
,
2939 pid
, tgid
, g_quark_from_string(command
),
2940 &s
->parent
.timestamp
);
2942 /* Keep the stack bottom : a running user mode */
2943 /* Disabled because of inconsistencies in the current statedump states. */
2944 if(type
== LTTV_STATE_KERNEL_THREAD
) {
2945 /* Only keep the bottom
2946 * FIXME Kernel thread : can be in syscall or interrupt or trap. */
2947 /* Will cause expected trap when in fact being syscall (even after end of
2949 * Will cause expected interrupt when being syscall. (only before end of
2950 * statedump event) */
2951 // This will cause a "popping last state on stack, ignoring it."
2952 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 1);
2953 es
= process
->state
= &g_array_index(process
->execution_stack
,
2954 LttvExecutionState
, 0);
2955 process
->type
= LTTV_STATE_KERNEL_THREAD
;
2956 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
2957 es
->s
= LTTV_STATE_UNNAMED
;
2958 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
2960 es
->t
= LTTV_STATE_SYSCALL
;
2965 /* User space process :
2966 * bottom : user mode
2967 * either currently running or scheduled out.
2968 * can be scheduled out because interrupted in (user mode or in syscall)
2969 * or because of an explicit call to the scheduler in syscall. Note that
2970 * the scheduler call comes after the irq_exit, so never in interrupt
2972 // temp workaround : set size to 1 : only have user mode bottom of stack.
2973 // will cause g_info message of expected syscall mode when in fact being
2974 // in user mode. Can also cause expected trap when in fact being user
2975 // mode in the event of a page fault reenabling interrupts in the handler.
2976 // Expected syscall and trap can also happen after the end of statedump
2977 // This will cause a "popping last state on stack, ignoring it."
2978 process
->execution_stack
= g_array_set_size(process
->execution_stack
, 1);
2979 es
= process
->state
= &g_array_index(process
->execution_stack
,
2980 LttvExecutionState
, 0);
2981 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
2982 es
->s
= LTTV_STATE_UNNAMED
;
2983 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
2985 es
->t
= LTTV_STATE_USER_MODE
;
2993 es
= process
->state
= &g_array_index(process
->execution_stack
,
2994 LttvExecutionState
, 1);
2995 es
->t
= LTTV_STATE_MODE_UNKNOWN
;
2996 es
->s
= LTTV_STATE_UNNAMED
;
2997 es
->n
= LTTV_STATE_SUBMODE_UNKNOWN
;
3001 /* The process has already been created :
3002 * Probably was forked while dumping the process state or
3003 * was simply scheduled in prior to get the state dump event.
3005 process
->ppid
= parent_pid
;
3006 process
->tgid
= tgid
;
3007 process
->name
= g_quark_from_string(command
);
3008 process
->type
= type
;
3010 &g_array_index(process
->execution_stack
, LttvExecutionState
, 0);
3012 if(es
->t
== LTTV_STATE_MODE_UNKNOWN
) {
3013 if(type
== LTTV_STATE_KERNEL_THREAD
)
3014 es
->t
= LTTV_STATE_SYSCALL
;
3016 es
->t
= LTTV_STATE_USER_MODE
;
3019 /* Don't mess around with the stack, it will eventually become
3020 * ok after the end of state dump. */
3027 gint
lttv_state_hook_add_event_hooks(void *hook_data
, void *call_data
)
3029 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
3031 lttv_state_add_event_hooks(tss
);
3036 void lttv_state_add_event_hooks(LttvTracesetState
*self
)
3038 LttvTraceset
*traceset
= self
->parent
.ts
;
3040 guint i
, j
, k
, l
, nb_trace
, nb_tracefile
;
3044 LttvTracefileState
*tfs
;
3048 LttvTraceHookByFacility
*thf
;
3050 LttvTraceHook
*hook
;
3052 LttvAttributeValue val
;
3057 nb_trace
= lttv_traceset_number(traceset
);
3058 for(i
= 0 ; i
< nb_trace
; i
++) {
3059 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
3061 /* Find the eventtype id for the following events and register the
3062 associated by id hooks. */
3064 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 19);
3065 hooks
= g_array_set_size(hooks
, 19); // Max possible number of hooks.
3068 ret
= lttv_trace_find_hook(ts
->parent
.t
,
3069 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_SYSCALL_ENTRY
,
3070 LTT_FIELD_SYSCALL_ID
, 0, 0,
3071 syscall_entry
, NULL
, &g_array_index(hooks
, LttvTraceHook
, hn
++));
3074 ret
= lttv_trace_find_hook(ts
->parent
.t
,
3075 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_SYSCALL_EXIT
,
3077 syscall_exit
, NULL
, &g_array_index(hooks
, LttvTraceHook
, hn
++));
3080 ret
= lttv_trace_find_hook(ts
->parent
.t
,
3081 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_TRAP_ENTRY
,
3082 LTT_FIELD_TRAP_ID
, 0, 0,
3083 trap_entry
, NULL
, &g_array_index(hooks
, LttvTraceHook
, hn
++));
3086 ret
= lttv_trace_find_hook(ts
->parent
.t
,
3087 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_TRAP_EXIT
,
3089 trap_exit
, NULL
, &g_array_index(hooks
, LttvTraceHook
, hn
++));
3092 ret
= lttv_trace_find_hook(ts
->parent
.t
,
3093 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_ENTRY
,
3094 LTT_FIELD_IRQ_ID
, 0, 0,
3095 irq_entry
, NULL
, &g_array_index(hooks
, LttvTraceHook
, hn
++));
3098 ret
= lttv_trace_find_hook(ts
->parent
.t
,
3099 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_EXIT
,
3101 irq_exit
, NULL
, &g_array_index(hooks
, LttvTraceHook
, hn
++));
3104 ret
= lttv_trace_find_hook(ts
->parent
.t
,
3105 LTT_FACILITY_KERNEL
, LTT_EVENT_SOFT_IRQ_ENTRY
,
3106 LTT_FIELD_SOFT_IRQ_ID
, 0, 0,
3107 soft_irq_entry
, NULL
, &g_array_index(hooks
, LttvTraceHook
, hn
++));
3110 ret
= lttv_trace_find_hook(ts
->parent
.t
,
3111 LTT_FACILITY_KERNEL
, LTT_EVENT_SOFT_IRQ_EXIT
,
3113 soft_irq_exit
, NULL
, &g_array_index(hooks
, LttvTraceHook
, hn
++));
3116 ret
= lttv_trace_find_hook(ts
->parent
.t
,
3117 LTT_FACILITY_KERNEL
, LTT_EVENT_SCHED_SCHEDULE
,
3118 LTT_FIELD_PREV_PID
, LTT_FIELD_NEXT_PID
, LTT_FIELD_PREV_STATE
,
3119 schedchange
, NULL
, &g_array_index(hooks
, LttvTraceHook
, hn
++));
3122 ret
= lttv_trace_find_hook(ts
->parent
.t
,
3123 LTT_FACILITY_KERNEL
, LTT_EVENT_PROCESS_FORK
,
3124 LTT_FIELD_PARENT_PID
, LTT_FIELD_CHILD_PID
, LTT_FIELD_CHILD_TGID
,
3125 process_fork
, NULL
, &g_array_index(hooks
, LttvTraceHook
, hn
++));
3128 ret
= lttv_trace_find_hook(ts
->parent
.t
,
3129 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_KTHREAD_CREATE
,
3130 LTT_FIELD_PID
, 0, 0,
3131 process_kernel_thread
, NULL
, &g_array_index(hooks
, LttvTraceHook
,
3135 ret
= lttv_trace_find_hook(ts
->parent
.t
,
3136 LTT_FACILITY_KERNEL
, LTT_EVENT_PROCESS_EXIT
,
3137 LTT_FIELD_PID
, 0, 0,
3138 process_exit
, NULL
, &g_array_index(hooks
, LttvTraceHook
, hn
++));
3141 ret
= lttv_trace_find_hook(ts
->parent
.t
,
3142 LTT_FACILITY_KERNEL
, LTT_EVENT_PROCESS_FREE
,
3143 LTT_FIELD_PID
, 0, 0,
3144 process_free
, NULL
, &g_array_index(hooks
, LttvTraceHook
, hn
++));
3147 ret
= lttv_trace_find_hook(ts
->parent
.t
,
3148 LTT_FACILITY_FS
, LTT_EVENT_EXEC
,
3149 LTT_FIELD_FILENAME
, 0, 0,
3150 process_exec
, NULL
, &g_array_index(hooks
, LttvTraceHook
, hn
++));
3153 ret
= lttv_trace_find_hook(ts
->parent
.t
,
3154 LTT_FACILITY_USER_GENERIC
, LTT_EVENT_THREAD_BRAND
,
3155 LTT_FIELD_NAME
, 0, 0,
3156 thread_brand
, NULL
, &g_array_index(hooks
, LttvTraceHook
, hn
++));
3159 /* statedump-related hooks */
3160 ret
= lttv_trace_find_hook(ts
->parent
.t
,
3161 LTT_FACILITY_LIST
, LTT_EVENT_PROCESS_STATE
,
3162 LTT_FIELD_PID
, LTT_FIELD_PARENT_PID
, LTT_FIELD_NAME
,
3163 enum_process_state
, NULL
, &g_array_index(hooks
, LttvTraceHook
, hn
++));
3166 ret
= lttv_trace_find_hook(ts
->parent
.t
,
3167 LTT_FACILITY_LIST
, LTT_EVENT_STATEDUMP_END
,
3169 statedump_end
, NULL
, &g_array_index(hooks
, LttvTraceHook
, hn
++));
3172 ret
= lttv_trace_find_hook(ts
->parent
.t
,
3173 LTT_FACILITY_BLOCK
, LTT_EVENT_REQUEST_ISSUE
,
3174 LTT_FIELD_MAJOR
, LTT_FIELD_MINOR
, LTT_FIELD_OPERATION
,
3175 bdev_request_issue
, NULL
, &g_array_index(hooks
, LttvTraceHook
, hn
++));
3178 ret
= lttv_trace_find_hook(ts
->parent
.t
,
3179 LTT_FACILITY_BLOCK
, LTT_EVENT_REQUEST_COMPLETE
,
3180 LTT_FIELD_MAJOR
, LTT_FIELD_MINOR
, LTT_FIELD_OPERATION
,
3181 bdev_request_complete
, NULL
, &g_array_index(hooks
, LttvTraceHook
, hn
++));
3184 ret
= lttv_trace_find_hook(ts
->parent
.t
,
3185 LTT_FACILITY_USER_GENERIC
, LTT_EVENT_FUNCTION_ENTRY
,
3186 LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
, 0,
3187 function_entry
, NULL
, &g_array_index(hooks
, LttvTraceHook
, hn
++));
3190 ret
= lttv_trace_find_hook(ts
->parent
.t
,
3191 LTT_FACILITY_USER_GENERIC
, LTT_EVENT_FUNCTION_EXIT
,
3192 LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
, 0,
3193 function_exit
, NULL
, &g_array_index(hooks
, LttvTraceHook
, hn
++));
3196 hooks
= g_array_set_size(hooks
, hn
);
3198 /* Add these hooks to each event_by_id hooks list */
3200 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3202 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3204 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
3205 LttvTracefileContext
*, j
));
3207 for(k
= 0 ; k
< hooks
->len
; k
++) {
3208 hook
= &g_array_index(hooks
, LttvTraceHook
, k
);
3209 for(l
=0;l
<hook
->fac_list
->len
;l
++) {
3210 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
3212 lttv_hooks_by_id_find(tfs
->parent
.event_by_id
, thf
->id
),
3219 lttv_attribute_find(ts
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
3220 *(val
.v_pointer
) = hooks
;
3224 gint
lttv_state_hook_remove_event_hooks(void *hook_data
, void *call_data
)
3226 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
3228 lttv_state_remove_event_hooks(tss
);
3233 void lttv_state_remove_event_hooks(LttvTracesetState
*self
)
3235 LttvTraceset
*traceset
= self
->parent
.ts
;
3237 guint i
, j
, k
, l
, nb_trace
, nb_tracefile
;
3241 LttvTracefileState
*tfs
;
3245 LttvTraceHook
*hook
;
3247 LttvTraceHookByFacility
*thf
;
3249 LttvAttributeValue val
;
3251 nb_trace
= lttv_traceset_number(traceset
);
3252 for(i
= 0 ; i
< nb_trace
; i
++) {
3253 ts
= LTTV_TRACE_STATE(self
->parent
.traces
[i
]);
3255 lttv_attribute_find(ts
->parent
.a
, LTTV_STATE_HOOKS
, LTTV_POINTER
, &val
);
3256 hooks
= *(val
.v_pointer
);
3258 /* Remove these hooks from each event_by_id hooks list */
3260 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3262 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3264 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
3265 LttvTracefileContext
*, j
));
3267 for(k
= 0 ; k
< hooks
->len
; k
++) {
3268 hook
= &g_array_index(hooks
, LttvTraceHook
, k
);
3269 for(l
=0;l
<hook
->fac_list
->len
;l
++) {
3270 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
3272 lttv_hooks_remove_data(
3273 lttv_hooks_by_id_find(tfs
->parent
.event_by_id
, thf
->id
),
3279 for(k
= 0 ; k
< hooks
->len
; k
++)
3280 lttv_trace_hook_destroy(&g_array_index(hooks
, LttvTraceHook
, k
));
3281 g_array_free(hooks
, TRUE
);
3285 static gboolean
state_save_event_hook(void *hook_data
, void *call_data
)
3287 guint
*event_count
= (guint
*)hook_data
;
3289 /* Only save at LTTV_STATE_SAVE_INTERVAL */
3290 if(likely((*event_count
)++ < LTTV_STATE_SAVE_INTERVAL
))
3295 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3297 LttvTracefileState
*tfcs
;
3299 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3301 LttEventPosition
*ep
;
3307 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
3309 LttvAttributeValue value
;
3311 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
3312 LTTV_STATE_SAVED_STATES
);
3313 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
3314 value
= lttv_attribute_add(saved_states_tree
,
3315 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
3316 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
3317 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
3318 *(value
.v_time
) = self
->parent
.timestamp
;
3319 lttv_state_save(tcs
, saved_state_tree
);
3320 g_debug("Saving state at time %lu.%lu", self
->parent
.timestamp
.tv_sec
,
3321 self
->parent
.timestamp
.tv_nsec
);
3323 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
3328 static gboolean
state_save_after_trace_hook(void *hook_data
, void *call_data
)
3330 LttvTraceState
*tcs
= (LttvTraceState
*)(call_data
);
3332 *(tcs
->max_time_state_recomputed_in_seek
) = tcs
->parent
.time_span
.end_time
;
3337 guint
lttv_state_current_cpu(LttvTracefileState
*tfs
)
3345 static gboolean
block_start(void *hook_data
, void *call_data
)
3347 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3349 LttvTracefileState
*tfcs
;
3351 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3353 LttEventPosition
*ep
;
3355 guint i
, nb_block
, nb_event
, nb_tracefile
;
3359 LttvAttribute
*saved_states_tree
, *saved_state_tree
;
3361 LttvAttributeValue value
;
3363 ep
= ltt_event_position_new();
3365 nb_tracefile
= tcs
->parent
.tracefiles
->len
;
3367 /* Count the number of events added since the last block end in any
3370 for(i
= 0 ; i
< nb_tracefile
; i
++) {
3372 LTTV_TRACEFILE_STATE(&g_array_index(tcs
->parent
.tracefiles
,
3373 LttvTracefileContext
, i
));
3374 ltt_event_position(tfcs
->parent
.e
, ep
);
3375 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
3376 tcs
->nb_event
+= nb_event
- tfcs
->saved_position
;
3377 tfcs
->saved_position
= nb_event
;
3381 if(tcs
->nb_event
>= tcs
->save_interval
) {
3382 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
3383 LTTV_STATE_SAVED_STATES
);
3384 saved_state_tree
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
3385 value
= lttv_attribute_add(saved_states_tree
,
3386 lttv_attribute_get_number(saved_states_tree
), LTTV_GOBJECT
);
3387 *(value
.v_gobject
) = (GObject
*)saved_state_tree
;
3388 value
= lttv_attribute_add(saved_state_tree
, LTTV_STATE_TIME
, LTTV_TIME
);
3389 *(value
.v_time
) = self
->parent
.timestamp
;
3390 lttv_state_save(tcs
, saved_state_tree
);
3392 g_debug("Saving state at time %lu.%lu", self
->parent
.timestamp
.tv_sec
,
3393 self
->parent
.timestamp
.tv_nsec
);
3395 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
3401 static gboolean
block_end(void *hook_data
, void *call_data
)
3403 LttvTracefileState
*self
= (LttvTracefileState
*)call_data
;
3405 LttvTraceState
*tcs
= (LttvTraceState
*)(self
->parent
.t_context
);
3409 LttEventPosition
*ep
;
3411 guint nb_block
, nb_event
;
3413 ep
= ltt_event_position_new();
3414 ltt_event_position(self
->parent
.e
, ep
);
3415 ltt_event_position_get(ep
, &nb_block
, &nb_event
, &tf
);
3416 tcs
->nb_event
+= nb_event
- self
->saved_position
+ 1;
3417 self
->saved_position
= 0;
3418 *(tcs
->max_time_state_recomputed_in_seek
) = self
->parent
.timestamp
;
3425 void lttv_state_save_add_event_hooks(LttvTracesetState
*self
)
3427 LttvTraceset
*traceset
= self
->parent
.ts
;
3429 guint i
, j
, nb_trace
, nb_tracefile
;
3433 LttvTracefileState
*tfs
;
3435 LttvTraceHook hook_start
, hook_end
;
3437 nb_trace
= lttv_traceset_number(traceset
);
3438 for(i
= 0 ; i
< nb_trace
; i
++) {
3439 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
3441 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
3442 NULL
, NULL
, block_start
, &hook_start
);
3443 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
3444 NULL
, NULL
, block_end
, &hook_end
);
3446 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3448 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3450 LTTV_TRACEFILE_STATE(&g_array_index(ts
->parent
.tracefiles
,
3451 LttvTracefileContext
, j
));
3452 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
3453 hook_start
.id
), hook_start
.h
, NULL
, LTTV_PRIO_STATE
);
3454 lttv_hooks_add(lttv_hooks_by_id_find(tfs
->parent
.event_by_id
,
3455 hook_end
.id
), hook_end
.h
, NULL
, LTTV_PRIO_STATE
);
3461 void lttv_state_save_add_event_hooks(LttvTracesetState
*self
)
3463 LttvTraceset
*traceset
= self
->parent
.ts
;
3465 guint i
, j
, nb_trace
, nb_tracefile
;
3469 LttvTracefileState
*tfs
;
3472 nb_trace
= lttv_traceset_number(traceset
);
3473 for(i
= 0 ; i
< nb_trace
; i
++) {
3475 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
3476 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3478 if(ts
->has_precomputed_states
) continue;
3480 guint
*event_count
= g_new(guint
, 1);
3483 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3485 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
3486 LttvTracefileContext
*, j
));
3487 lttv_hooks_add(tfs
->parent
.event
,
3488 state_save_event_hook
,
3495 lttv_process_traceset_begin(&self
->parent
,
3496 NULL
, NULL
, NULL
, NULL
, NULL
);
3500 gint
lttv_state_save_hook_add_event_hooks(void *hook_data
, void *call_data
)
3502 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
3504 lttv_state_save_add_event_hooks(tss
);
3511 void lttv_state_save_remove_event_hooks(LttvTracesetState
*self
)
3513 LttvTraceset
*traceset
= self
->parent
.ts
;
3515 guint i
, j
, nb_trace
, nb_tracefile
;
3519 LttvTracefileState
*tfs
;
3521 LttvTraceHook hook_start
, hook_end
;
3523 nb_trace
= lttv_traceset_number(traceset
);
3524 for(i
= 0 ; i
< nb_trace
; i
++) {
3525 ts
= LTTV_TRACE_STATE(self
->parent
.traces
[i
]);
3527 lttv_trace_find_hook(ts
->parent
.t
, "core","block_start",NULL
,
3528 NULL
, NULL
, block_start
, &hook_start
);
3530 lttv_trace_find_hook(ts
->parent
.t
, "core","block_end",NULL
,
3531 NULL
, NULL
, block_end
, &hook_end
);
3533 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3535 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3537 LTTV_TRACEFILE_STATE(&g_array_index(ts
->parent
.tracefiles
,
3538 LttvTracefileContext
, j
));
3539 lttv_hooks_remove_data(lttv_hooks_by_id_find(
3540 tfs
->parent
.event_by_id
, hook_start
.id
), hook_start
.h
, NULL
);
3541 lttv_hooks_remove_data(lttv_hooks_by_id_find(
3542 tfs
->parent
.event_by_id
, hook_end
.id
), hook_end
.h
, NULL
);
3548 void lttv_state_save_remove_event_hooks(LttvTracesetState
*self
)
3550 LttvTraceset
*traceset
= self
->parent
.ts
;
3552 guint i
, j
, nb_trace
, nb_tracefile
;
3556 LttvTracefileState
*tfs
;
3558 LttvHooks
*after_trace
= lttv_hooks_new();
3560 lttv_hooks_add(after_trace
,
3561 state_save_after_trace_hook
,
3566 lttv_process_traceset_end(&self
->parent
,
3567 NULL
, after_trace
, NULL
, NULL
, NULL
);
3569 lttv_hooks_destroy(after_trace
);
3571 nb_trace
= lttv_traceset_number(traceset
);
3572 for(i
= 0 ; i
< nb_trace
; i
++) {
3574 ts
= (LttvTraceState
*)self
->parent
.traces
[i
];
3575 nb_tracefile
= ts
->parent
.tracefiles
->len
;
3577 if(ts
->has_precomputed_states
) continue;
3579 guint
*event_count
= NULL
;
3581 for(j
= 0 ; j
< nb_tracefile
; j
++) {
3583 LTTV_TRACEFILE_STATE(g_array_index(ts
->parent
.tracefiles
,
3584 LttvTracefileContext
*, j
));
3585 event_count
= lttv_hooks_remove(tfs
->parent
.event
,
3586 state_save_event_hook
);
3588 if(event_count
) g_free(event_count
);
3592 gint
lttv_state_save_hook_remove_event_hooks(void *hook_data
, void *call_data
)
3594 LttvTracesetState
*tss
= (LttvTracesetState
*)(call_data
);
3596 lttv_state_save_remove_event_hooks(tss
);
3601 void lttv_state_traceset_seek_time_closest(LttvTracesetState
*self
, LttTime t
)
3603 LttvTraceset
*traceset
= self
->parent
.ts
;
3607 int min_pos
, mid_pos
, max_pos
;
3609 guint call_rest
= 0;
3611 LttvTraceState
*tcs
;
3613 LttvAttributeValue value
;
3615 LttvAttributeType type
;
3617 LttvAttributeName name
;
3621 LttvAttribute
*saved_states_tree
, *saved_state_tree
, *closest_tree
;
3623 //g_tree_destroy(self->parent.pqueue);
3624 //self->parent.pqueue = g_tree_new(compare_tracefile);
3626 g_info("Entering seek_time_closest for time %lu.%lu", t
.tv_sec
, t
.tv_nsec
);
3628 nb_trace
= lttv_traceset_number(traceset
);
3629 for(i
= 0 ; i
< nb_trace
; i
++) {
3630 tcs
= (LttvTraceState
*)self
->parent
.traces
[i
];
3632 if(ltt_time_compare(t
, *(tcs
->max_time_state_recomputed_in_seek
)) < 0) {
3633 saved_states_tree
= lttv_attribute_find_subdir(tcs
->parent
.t_a
,
3634 LTTV_STATE_SAVED_STATES
);
3637 if(saved_states_tree
) {
3638 max_pos
= lttv_attribute_get_number(saved_states_tree
) - 1;
3639 mid_pos
= max_pos
/ 2;
3640 while(min_pos
< max_pos
) {
3641 type
= lttv_attribute_get(saved_states_tree
, mid_pos
, &name
, &value
,
3643 g_assert(type
== LTTV_GOBJECT
);
3644 saved_state_tree
= *((LttvAttribute
**)(value
.v_gobject
));
3645 type
= lttv_attribute_get_by_name(saved_state_tree
, LTTV_STATE_TIME
,
3647 g_assert(type
== LTTV_TIME
);
3648 if(ltt_time_compare(*(value
.v_time
), t
) < 0) {
3650 closest_tree
= saved_state_tree
;
3652 else max_pos
= mid_pos
- 1;
3654 mid_pos
= (min_pos
+ max_pos
+ 1) / 2;
3658 /* restore the closest earlier saved state */
3660 lttv_state_restore(tcs
, closest_tree
);
3664 /* There is no saved state, yet we want to have it. Restart at T0 */
3666 restore_init_state(tcs
);
3667 lttv_process_trace_seek_time(&(tcs
->parent
), ltt_time_zero
);
3670 /* We want to seek quickly without restoring/updating the state */
3672 restore_init_state(tcs
);
3673 lttv_process_trace_seek_time(&(tcs
->parent
), t
);
3676 if(!call_rest
) g_info("NOT Calling restore");
3681 traceset_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
3687 traceset_state_finalize (LttvTracesetState
*self
)
3689 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE
))->
3690 finalize(G_OBJECT(self
));
3695 traceset_state_class_init (LttvTracesetContextClass
*klass
)
3697 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
3699 gobject_class
->finalize
= (void (*)(GObject
*self
)) traceset_state_finalize
;
3700 klass
->init
= (void (*)(LttvTracesetContext
*self
, LttvTraceset
*ts
))init
;
3701 klass
->fini
= (void (*)(LttvTracesetContext
*self
))fini
;
3702 klass
->new_traceset_context
= new_traceset_context
;
3703 klass
->new_trace_context
= new_trace_context
;
3704 klass
->new_tracefile_context
= new_tracefile_context
;
3709 lttv_traceset_state_get_type(void)
3711 static GType type
= 0;
3713 static const GTypeInfo info
= {
3714 sizeof (LttvTracesetStateClass
),
3715 NULL
, /* base_init */
3716 NULL
, /* base_finalize */
3717 (GClassInitFunc
) traceset_state_class_init
, /* class_init */
3718 NULL
, /* class_finalize */
3719 NULL
, /* class_data */
3720 sizeof (LttvTracesetState
),
3721 0, /* n_preallocs */
3722 (GInstanceInitFunc
) traceset_state_instance_init
, /* instance_init */
3723 NULL
/* value handling */
3726 type
= g_type_register_static (LTTV_TRACESET_CONTEXT_TYPE
, "LttvTracesetStateType",
3734 trace_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
3740 trace_state_finalize (LttvTraceState
*self
)
3742 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_CONTEXT_TYPE
))->
3743 finalize(G_OBJECT(self
));
3748 trace_state_class_init (LttvTraceStateClass
*klass
)
3750 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
3752 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_state_finalize
;
3753 klass
->state_save
= state_save
;
3754 klass
->state_restore
= state_restore
;
3755 klass
->state_saved_free
= state_saved_free
;
3760 lttv_trace_state_get_type(void)
3762 static GType type
= 0;
3764 static const GTypeInfo info
= {
3765 sizeof (LttvTraceStateClass
),
3766 NULL
, /* base_init */
3767 NULL
, /* base_finalize */
3768 (GClassInitFunc
) trace_state_class_init
, /* class_init */
3769 NULL
, /* class_finalize */
3770 NULL
, /* class_data */
3771 sizeof (LttvTraceState
),
3772 0, /* n_preallocs */
3773 (GInstanceInitFunc
) trace_state_instance_init
, /* instance_init */
3774 NULL
/* value handling */
3777 type
= g_type_register_static (LTTV_TRACE_CONTEXT_TYPE
,
3778 "LttvTraceStateType", &info
, 0);
3785 tracefile_state_instance_init (GTypeInstance
*instance
, gpointer g_class
)
3791 tracefile_state_finalize (LttvTracefileState
*self
)
3793 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_CONTEXT_TYPE
))->
3794 finalize(G_OBJECT(self
));
3799 tracefile_state_class_init (LttvTracefileStateClass
*klass
)
3801 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
3803 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_state_finalize
;
3808 lttv_tracefile_state_get_type(void)
3810 static GType type
= 0;
3812 static const GTypeInfo info
= {
3813 sizeof (LttvTracefileStateClass
),
3814 NULL
, /* base_init */
3815 NULL
, /* base_finalize */
3816 (GClassInitFunc
) tracefile_state_class_init
, /* class_init */
3817 NULL
, /* class_finalize */
3818 NULL
, /* class_data */
3819 sizeof (LttvTracefileState
),
3820 0, /* n_preallocs */
3821 (GInstanceInitFunc
) tracefile_state_instance_init
, /* instance_init */
3822 NULL
/* value handling */
3825 type
= g_type_register_static (LTTV_TRACEFILE_CONTEXT_TYPE
,
3826 "LttvTracefileStateType", &info
, 0);
3832 static void module_init()
3834 LTTV_STATE_UNNAMED
= g_quark_from_string("UNNAMED");
3835 LTTV_STATE_UNBRANDED
= g_quark_from_string("UNBRANDED");
3836 LTTV_STATE_MODE_UNKNOWN
= g_quark_from_string("MODE_UNKNOWN");
3837 LTTV_STATE_USER_MODE
= g_quark_from_string("USER_MODE");
3838 LTTV_STATE_SYSCALL
= g_quark_from_string("SYSCALL");
3839 LTTV_STATE_TRAP
= g_quark_from_string("TRAP");
3840 LTTV_STATE_IRQ
= g_quark_from_string("IRQ");
3841 LTTV_STATE_SOFT_IRQ
= g_quark_from_string("SOFTIRQ");
3842 LTTV_STATE_SUBMODE_UNKNOWN
= g_quark_from_string("UNKNOWN");
3843 LTTV_STATE_SUBMODE_NONE
= g_quark_from_string("NONE");
3844 LTTV_STATE_WAIT_FORK
= g_quark_from_string("WAIT_FORK");
3845 LTTV_STATE_WAIT_CPU
= g_quark_from_string("WAIT_CPU");
3846 LTTV_STATE_EXIT
= g_quark_from_string("EXIT");
3847 LTTV_STATE_ZOMBIE
= g_quark_from_string("ZOMBIE");
3848 LTTV_STATE_WAIT
= g_quark_from_string("WAIT");
3849 LTTV_STATE_RUN
= g_quark_from_string("RUN");
3850 LTTV_STATE_DEAD
= g_quark_from_string("DEAD");
3851 LTTV_STATE_USER_THREAD
= g_quark_from_string("USER_THREAD");
3852 LTTV_STATE_KERNEL_THREAD
= g_quark_from_string("KERNEL_THREAD");
3853 LTTV_STATE_TRACEFILES
= g_quark_from_string("tracefiles");
3854 LTTV_STATE_PROCESSES
= g_quark_from_string("processes");
3855 LTTV_STATE_PROCESS
= g_quark_from_string("process");
3856 LTTV_STATE_RUNNING_PROCESS
= g_quark_from_string("running_process");
3857 LTTV_STATE_EVENT
= g_quark_from_string("event");
3858 LTTV_STATE_SAVED_STATES
= g_quark_from_string("saved states");
3859 LTTV_STATE_SAVED_STATES_TIME
= g_quark_from_string("saved states time");
3860 LTTV_STATE_TIME
= g_quark_from_string("time");
3861 LTTV_STATE_HOOKS
= g_quark_from_string("saved state hooks");
3862 LTTV_STATE_NAME_TABLES
= g_quark_from_string("name tables");
3863 LTTV_STATE_TRACE_STATE_USE_COUNT
=
3864 g_quark_from_string("trace_state_use_count");
3865 LTTV_STATE_RESOURCE_CPUS
= g_quark_from_string("cpu resource states");
3866 LTTV_STATE_RESOURCE_IRQS
= g_quark_from_string("irq resource states");
3867 LTTV_STATE_RESOURCE_BLKDEVS
= g_quark_from_string("blkdevs resource states");
3870 LTT_FACILITY_KERNEL
= g_quark_from_string("kernel");
3871 LTT_FACILITY_KERNEL_ARCH
= g_quark_from_string("kernel_arch");
3872 LTT_FACILITY_FS
= g_quark_from_string("fs");
3873 LTT_FACILITY_LIST
= g_quark_from_string("list");
3874 LTT_FACILITY_USER_GENERIC
= g_quark_from_string("user_generic");
3875 LTT_FACILITY_BLOCK
= g_quark_from_string("block");
3878 LTT_EVENT_SYSCALL_ENTRY
= g_quark_from_string("syscall_entry");
3879 LTT_EVENT_SYSCALL_EXIT
= g_quark_from_string("syscall_exit");
3880 LTT_EVENT_TRAP_ENTRY
= g_quark_from_string("trap_entry");
3881 LTT_EVENT_TRAP_EXIT
= g_quark_from_string("trap_exit");
3882 LTT_EVENT_IRQ_ENTRY
= g_quark_from_string("irq_entry");
3883 LTT_EVENT_IRQ_EXIT
= g_quark_from_string("irq_exit");
3884 LTT_EVENT_SOFT_IRQ_ENTRY
= g_quark_from_string("soft_irq_entry");
3885 LTT_EVENT_SOFT_IRQ_EXIT
= g_quark_from_string("soft_irq_exit");
3886 LTT_EVENT_SCHED_SCHEDULE
= g_quark_from_string("sched_schedule");
3887 LTT_EVENT_PROCESS_FORK
= g_quark_from_string("process_fork");
3888 LTT_EVENT_KTHREAD_CREATE
= g_quark_from_string("kthread_create");
3889 LTT_EVENT_PROCESS_EXIT
= g_quark_from_string("process_exit");
3890 LTT_EVENT_PROCESS_FREE
= g_quark_from_string("process_free");
3891 LTT_EVENT_EXEC
= g_quark_from_string("exec");
3892 LTT_EVENT_PROCESS_STATE
= g_quark_from_string("process_state");
3893 LTT_EVENT_STATEDUMP_END
= g_quark_from_string("statedump_end");
3894 LTT_EVENT_FUNCTION_ENTRY
= g_quark_from_string("function_entry");
3895 LTT_EVENT_FUNCTION_EXIT
= g_quark_from_string("function_exit");
3896 LTT_EVENT_THREAD_BRAND
= g_quark_from_string("thread_brand");
3897 LTT_EVENT_REQUEST_ISSUE
= g_quark_from_string("_blk_request_issue");
3898 LTT_EVENT_REQUEST_COMPLETE
= g_quark_from_string("_blk_request_complete");
3901 LTT_FIELD_SYSCALL_ID
= g_quark_from_string("syscall_id");
3902 LTT_FIELD_TRAP_ID
= g_quark_from_string("trap_id");
3903 LTT_FIELD_IRQ_ID
= g_quark_from_string("irq_id");
3904 LTT_FIELD_SOFT_IRQ_ID
= g_quark_from_string("softirq_id");
3905 LTT_FIELD_PREV_PID
= g_quark_from_string("prev_pid");
3906 LTT_FIELD_NEXT_PID
= g_quark_from_string("next_pid");
3907 LTT_FIELD_PREV_STATE
= g_quark_from_string("prev_state");
3908 LTT_FIELD_PARENT_PID
= g_quark_from_string("parent_pid");
3909 LTT_FIELD_CHILD_PID
= g_quark_from_string("child_pid");
3910 LTT_FIELD_PID
= g_quark_from_string("pid");
3911 LTT_FIELD_TGID
= g_quark_from_string("tgid");
3912 LTT_FIELD_CHILD_TGID
= g_quark_from_string("child_tgid");
3913 LTT_FIELD_FILENAME
= g_quark_from_string("filename");
3914 LTT_FIELD_NAME
= g_quark_from_string("name");
3915 LTT_FIELD_TYPE
= g_quark_from_string("type");
3916 LTT_FIELD_MODE
= g_quark_from_string("mode");
3917 LTT_FIELD_SUBMODE
= g_quark_from_string("submode");
3918 LTT_FIELD_STATUS
= g_quark_from_string("status");
3919 LTT_FIELD_THIS_FN
= g_quark_from_string("this_fn");
3920 LTT_FIELD_CALL_SITE
= g_quark_from_string("call_site");
3921 LTT_FIELD_MAJOR
= g_quark_from_string("major");
3922 LTT_FIELD_MINOR
= g_quark_from_string("minor");
3923 LTT_FIELD_OPERATION
= g_quark_from_string("direction");
3925 LTTV_CPU_UNKNOWN
= g_quark_from_string("unknown");
3926 LTTV_CPU_IDLE
= g_quark_from_string("idle");
3927 LTTV_CPU_BUSY
= g_quark_from_string("busy");
3928 LTTV_CPU_IRQ
= g_quark_from_string("irq");
3929 LTTV_CPU_TRAP
= g_quark_from_string("trap");
3931 LTTV_IRQ_UNKNOWN
= g_quark_from_string("unknown");
3932 LTTV_IRQ_IDLE
= g_quark_from_string("idle");
3933 LTTV_IRQ_BUSY
= g_quark_from_string("busy");
3935 LTTV_BDEV_UNKNOWN
= g_quark_from_string("unknown");
3936 LTTV_BDEV_IDLE
= g_quark_from_string("idle");
3937 LTTV_BDEV_BUSY_READING
= g_quark_from_string("busy_reading");
3938 LTTV_BDEV_BUSY_WRITING
= g_quark_from_string("busy_writing");
3941 static void module_destroy()
3946 LTTV_MODULE("state", "State computation", \
3947 "Update the system state, possibly saving it at intervals", \
3948 module_init
, module_destroy
)