traceset position save fix
[lttv.git] / ltt / branches / poly / lttv / lttv / state.c
1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Michel Dagenais
3 *
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;
7 *
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.
12 *
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,
16 * MA 02111-1307, USA.
17 */
18
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22
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>
29 #include <ltt/type.h>
30 #include <stdio.h>
31
32 #define PREALLOCATED_EXECUTION_STACK 10
33
34 /* Facilities Quarks */
35
36 GQuark
37 LTT_FACILITY_KERNEL,
38 LTT_FACILITY_PROCESS;
39
40 /* Events Quarks */
41
42 GQuark
43 LTT_EVENT_SYSCALL_ENTRY,
44 LTT_EVENT_SYSCALL_EXIT,
45 LTT_EVENT_TRAP_ENTRY,
46 LTT_EVENT_TRAP_EXIT,
47 LTT_EVENT_IRQ_ENTRY,
48 LTT_EVENT_IRQ_EXIT,
49 LTT_EVENT_SCHEDCHANGE,
50 LTT_EVENT_FORK,
51 LTT_EVENT_EXIT,
52 LTT_EVENT_FREE;
53
54 /* Fields Quarks */
55
56 GQuark
57 LTT_FIELD_SYSCALL_ID,
58 LTT_FIELD_TRAP_ID,
59 LTT_FIELD_IRQ_ID,
60 LTT_FIELD_OUT,
61 LTT_FIELD_IN,
62 LTT_FIELD_OUT_STATE,
63 LTT_FIELD_PARENT_PID,
64 LTT_FIELD_CHILD_PID,
65 LTT_FIELD_PID;
66
67 LttvExecutionMode
68 LTTV_STATE_MODE_UNKNOWN,
69 LTTV_STATE_USER_MODE,
70 LTTV_STATE_SYSCALL,
71 LTTV_STATE_TRAP,
72 LTTV_STATE_IRQ;
73
74 LttvExecutionSubmode
75 LTTV_STATE_SUBMODE_UNKNOWN,
76 LTTV_STATE_SUBMODE_NONE;
77
78 LttvProcessStatus
79 LTTV_STATE_UNNAMED,
80 LTTV_STATE_WAIT_FORK,
81 LTTV_STATE_WAIT_CPU,
82 LTTV_STATE_EXIT,
83 LTTV_STATE_ZOMBIE,
84 LTTV_STATE_WAIT,
85 LTTV_STATE_RUN;
86
87 static GQuark
88 LTTV_STATE_TRACEFILES,
89 LTTV_STATE_PROCESSES,
90 LTTV_STATE_PROCESS,
91 LTTV_STATE_RUNNING_PROCESS,
92 LTTV_STATE_EVENT,
93 LTTV_STATE_SAVED_STATES,
94 LTTV_STATE_SAVED_STATES_TIME,
95 LTTV_STATE_TIME,
96 LTTV_STATE_HOOKS,
97 LTTV_STATE_NAME_TABLES,
98 LTTV_STATE_TRACE_STATE_USE_COUNT;
99
100 static void create_max_time(LttvTraceState *tcs);
101
102 static void get_max_time(LttvTraceState *tcs);
103
104 static void free_max_time(LttvTraceState *tcs);
105
106 static void create_name_tables(LttvTraceState *tcs);
107
108 static void get_name_tables(LttvTraceState *tcs);
109
110 static void free_name_tables(LttvTraceState *tcs);
111
112 static void free_saved_state(LttvTraceState *tcs);
113
114 static void lttv_state_free_process_table(GHashTable *processes);
115
116
117 void lttv_state_save(LttvTraceState *self, LttvAttribute *container)
118 {
119 LTTV_TRACE_STATE_GET_CLASS(self)->state_save(self, container);
120 }
121
122
123 void lttv_state_restore(LttvTraceState *self, LttvAttribute *container)
124 {
125 LTTV_TRACE_STATE_GET_CLASS(self)->state_restore(self, container);
126 }
127
128
129 void lttv_state_state_saved_free(LttvTraceState *self,
130 LttvAttribute *container)
131 {
132 LTTV_TRACE_STATE_GET_CLASS(self)->state_saved_free(self, container);
133 }
134
135
136 guint process_hash(gconstpointer key)
137 {
138 guint pid = ((const LttvProcessState *)key)->pid;
139 return (pid>>8 ^ pid>>4 ^ pid>>2 ^ pid) ;
140 }
141
142
143 /* If the hash table hash function is well distributed,
144 * the process_equal should compare different pid */
145 gboolean process_equal(gconstpointer a, gconstpointer b)
146 {
147 const LttvProcessState *process_a, *process_b;
148 gboolean ret = TRUE;
149
150 process_a = (const LttvProcessState *)a;
151 process_b = (const LttvProcessState *)b;
152
153 if(likely(process_a->pid != process_b->pid)) ret = FALSE;
154 else if(likely(process_a->pid == 0 &&
155 process_a->cpu != process_b->cpu)) ret = FALSE;
156
157 return ret;
158 }
159
160
161 static void
162 restore_init_state(LttvTraceState *self)
163 {
164 guint i, nb_cpus;
165
166 LttvTracefileState *tfcs;
167
168 /* Free the process tables */
169 if(self->processes != NULL) lttv_state_free_process_table(self->processes);
170 self->processes = g_hash_table_new(process_hash, process_equal);
171 self->nb_event = 0;
172
173 /* Seek time to beginning */
174 g_tree_destroy(self->parent.ts_context->pqueue);
175 self->parent.ts_context->pqueue = g_tree_new(compare_tracefile);
176
177 lttv_process_trace_seek_time(&self->parent, ltt_time_zero);
178
179 nb_cpus = ltt_trace_get_num_cpu(self->parent.t);
180
181 /* Put the per cpu running_process to beginning state : process 0. */
182 for(i=0; i< nb_cpus; i++) {
183 self->running_process[i] = lttv_state_create_process(self, NULL, i, 0,
184 &ltt_time_zero);
185 self->running_process[i]->state->s = LTTV_STATE_RUN;
186 self->running_process[i]->cpu = i;
187 }
188
189 #if 0
190 nb_tracefile = self->parent.tracefiles->len;
191
192 for(i = 0 ; i < nb_tracefile ; i++) {
193 tfcs =
194 LTTV_TRACEFILE_STATE(g_array_index(self->parent.tracefiles,
195 LttvTracefileContext*, i));
196 ltt_trace_time_span_get(self->parent.t, &tfcs->parent.timestamp, NULL);
197 // tfcs->saved_position = 0;
198 tfcs->process = lttv_state_create_process(tfcs, NULL,0);
199 tfcs->process->state->s = LTTV_STATE_RUN;
200 tfcs->process->last_cpu = tfcs->cpu_name;
201 tfcs->process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfcs)->tf);
202 }
203 #endif //0
204 }
205
206 //static LttTime time_zero = {0,0};
207
208 static void
209 init(LttvTracesetState *self, LttvTraceset *ts)
210 {
211 guint i, j, nb_trace, nb_tracefile;
212
213 LttvTraceContext *tc;
214
215 LttvTraceState *tcs;
216
217 LttvTracefileState *tfcs;
218
219 LttvAttributeValue v;
220
221 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))->
222 init((LttvTracesetContext *)self, ts);
223
224 nb_trace = lttv_traceset_number(ts);
225 for(i = 0 ; i < nb_trace ; i++) {
226 tc = self->parent.traces[i];
227 tcs = LTTV_TRACE_STATE(tc);
228 tcs->save_interval = LTTV_STATE_SAVE_INTERVAL;
229 lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_TRACE_STATE_USE_COUNT,
230 LTTV_UINT, &v);
231 (*v.v_uint)++;
232
233 if(*(v.v_uint) == 1) {
234 create_name_tables(tcs);
235 create_max_time(tcs);
236 }
237 get_name_tables(tcs);
238 get_max_time(tcs);
239
240 nb_tracefile = tc->tracefiles->len;
241 #if 0
242 for(j = 0 ; j < nb_tracefile ; j++) {
243 tfcs =
244 LTTV_TRACEFILE_STATE(g_array_index(tc->tracefiles,
245 LttvTracefileContext*, j));
246 tfcs->tracefile_name = ltt_tracefile_name(tfcs->parent.tf);
247 }
248 #endif //0
249 tcs->processes = NULL;
250 tcs->running_process = g_new(LttvProcessState*,
251 ltt_trace_get_num_cpu(tc->t));
252 restore_init_state(tcs);
253 }
254 }
255
256
257 static void
258 fini(LttvTracesetState *self)
259 {
260 guint i, nb_trace;
261
262 LttvTraceState *tcs;
263
264 LttvTracefileState *tfcs;
265
266 LttvAttributeValue v;
267
268 nb_trace = lttv_traceset_number(LTTV_TRACESET_CONTEXT(self)->ts);
269 for(i = 0 ; i < nb_trace ; i++) {
270 tcs = (LttvTraceState *)(LTTV_TRACESET_CONTEXT(self)->traces[i]);
271 lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_TRACE_STATE_USE_COUNT,
272 LTTV_UINT, &v);
273
274 g_assert(*(v.v_uint) != 0);
275 (*v.v_uint)--;
276
277 if(*(v.v_uint) == 0) {
278 free_name_tables(tcs);
279 free_max_time(tcs);
280 free_saved_state(tcs);
281 }
282 g_free(tcs->running_process);
283 tcs->running_process = NULL;
284 lttv_state_free_process_table(tcs->processes);
285 tcs->processes = NULL;
286 }
287 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))->
288 fini((LttvTracesetContext *)self);
289 }
290
291
292 static LttvTracesetContext *
293 new_traceset_context(LttvTracesetContext *self)
294 {
295 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATE_TYPE, NULL));
296 }
297
298
299 static LttvTraceContext *
300 new_trace_context(LttvTracesetContext *self)
301 {
302 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATE_TYPE, NULL));
303 }
304
305
306 static LttvTracefileContext *
307 new_tracefile_context(LttvTracesetContext *self)
308 {
309 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATE_TYPE, NULL));
310 }
311
312
313 /* Write the process state of the trace */
314
315 static void write_process_state(gpointer key, gpointer value,
316 gpointer user_data)
317 {
318 LttvProcessState *process;
319
320 LttvExecutionState *es;
321
322 FILE *fp = (FILE *)user_data;
323
324 guint i;
325
326 process = (LttvProcessState *)value;
327 fprintf(fp,
328 " <PROCESS CORE=%p PID=%u PPID=%u CTIME_S=%lu CTIME_NS=%lu NAME=\"%s\" CPU=\"%u\">\n",
329 process, process->pid, process->ppid, process->creation_time.tv_sec,
330 process->creation_time.tv_nsec, g_quark_to_string(process->name),
331 process->cpu);
332
333 for(i = 0 ; i < process->execution_stack->len; i++) {
334 es = &g_array_index(process->execution_stack, LttvExecutionState, i);
335 fprintf(fp, " <ES MODE=\"%s\" SUBMODE=\"%s\" ENTRY_S=%lu ENTRY_NS=%lu",
336 g_quark_to_string(es->t), g_quark_to_string(es->n),
337 es->entry.tv_sec, es->entry.tv_nsec);
338 fprintf(fp, " CHANGE_S=%lu CHANGE_NS=%lu STATUS=\"%s\"/>\n",
339 es->change.tv_sec, es->change.tv_nsec, g_quark_to_string(es->s));
340 }
341 fprintf(fp, " </PROCESS>\n");
342 }
343
344
345 void lttv_state_write(LttvTraceState *self, LttTime t, FILE *fp)
346 {
347 guint i, nb_tracefile, nb_block, offset;
348 guint64 tsc;
349
350 LttvTracefileState *tfcs;
351
352 LttTracefile *tf;
353
354 LttEventPosition *ep;
355
356 guint nb_cpus;
357
358 ep = ltt_event_position_new();
359
360 fprintf(fp,"<PROCESS_STATE TIME_S=%lu TIME_NS=%lu>\n", t.tv_sec, t.tv_nsec);
361
362 g_hash_table_foreach(self->processes, write_process_state, fp);
363
364 nb_cpus = ltt_trace_get_num_cpu(self->parent.t);
365 for(i=0;i<nb_cpus;i++) {
366 fprintf(fp,"<CPU NUM=%u RUNNING_PROCESS=%u>\n",
367 i, self->running_process[i]->pid);
368 }
369
370 nb_tracefile = self->parent.tracefiles->len;
371
372 for(i = 0 ; i < nb_tracefile ; i++) {
373 tfcs =
374 LTTV_TRACEFILE_STATE(g_array_index(self->parent.tracefiles,
375 LttvTracefileContext*, i));
376 fprintf(fp, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
377 tfcs->parent.timestamp.tv_sec,
378 tfcs->parent.timestamp.tv_nsec);
379 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.tf);
380 if(e == NULL) fprintf(fp,"/>\n");
381 else {
382 ltt_event_position(e, ep);
383 ltt_event_position_get(ep, &tf, &nb_block, &offset, &tsc);
384 fprintf(fp, " BLOCK=%u OFFSET=%u TSC=%llu/>\n", nb_block, offset,
385 tsc);
386 }
387 }
388 g_free(ep);
389 fprintf(fp,"</PROCESS_STATE>");
390 }
391
392
393 /* Copy each process from an existing hash table to a new one */
394
395 static void copy_process_state(gpointer key, gpointer value,gpointer user_data)
396 {
397 LttvProcessState *process, *new_process;
398
399 GHashTable *new_processes = (GHashTable *)user_data;
400
401 guint i;
402
403 process = (LttvProcessState *)value;
404 new_process = g_new(LttvProcessState, 1);
405 *new_process = *process;
406 new_process->execution_stack = g_array_sized_new(FALSE, FALSE,
407 sizeof(LttvExecutionState), PREALLOCATED_EXECUTION_STACK);
408 new_process->execution_stack =
409 g_array_set_size(new_process->execution_stack,
410 process->execution_stack->len);
411 for(i = 0 ; i < process->execution_stack->len; i++) {
412 g_array_index(new_process->execution_stack, LttvExecutionState, i) =
413 g_array_index(process->execution_stack, LttvExecutionState, i);
414 }
415 new_process->state = &g_array_index(new_process->execution_stack,
416 LttvExecutionState, new_process->execution_stack->len - 1);
417 g_hash_table_insert(new_processes, new_process, new_process);
418 }
419
420
421 static GHashTable *lttv_state_copy_process_table(GHashTable *processes)
422 {
423 GHashTable *new_processes = g_hash_table_new(process_hash, process_equal);
424
425 g_hash_table_foreach(processes, copy_process_state, new_processes);
426 return new_processes;
427 }
428
429
430 /* The saved state for each trace contains a member "processes", which
431 stores a copy of the process table, and a member "tracefiles" with
432 one entry per tracefile. Each tracefile has a "process" member pointing
433 to the current process and a "position" member storing the tracefile
434 position (needed to seek to the current "next" event. */
435
436 static void state_save(LttvTraceState *self, LttvAttribute *container)
437 {
438 guint i, nb_tracefile, nb_cpus;
439
440 LttvTracefileState *tfcs;
441
442 LttvAttribute *tracefiles_tree, *tracefile_tree;
443
444 guint *running_process;
445
446 LttvAttributeType type;
447
448 LttvAttributeValue value;
449
450 LttvAttributeName name;
451
452 LttEventPosition *ep;
453
454 tracefiles_tree = lttv_attribute_find_subdir(container,
455 LTTV_STATE_TRACEFILES);
456
457 value = lttv_attribute_add(container, LTTV_STATE_PROCESSES,
458 LTTV_POINTER);
459 *(value.v_pointer) = lttv_state_copy_process_table(self->processes);
460
461 /* Add the currently running processes array */
462 nb_cpus = ltt_trace_get_num_cpu(self->parent.t);
463 running_process = g_new(guint, nb_cpus);
464 for(i=0;i<nb_cpus;i++) {
465 running_process[i] = self->running_process[i]->pid;
466 }
467 value = lttv_attribute_add(container, LTTV_STATE_RUNNING_PROCESS,
468 LTTV_POINTER);
469 *(value.v_pointer) = running_process;
470
471 g_info("State save");
472
473 nb_tracefile = self->parent.tracefiles->len;
474
475 for(i = 0 ; i < nb_tracefile ; i++) {
476 tfcs =
477 LTTV_TRACEFILE_STATE(g_array_index(self->parent.tracefiles,
478 LttvTracefileContext*, i));
479 tracefile_tree = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
480 value = lttv_attribute_add(tracefiles_tree, i,
481 LTTV_GOBJECT);
482 *(value.v_gobject) = (GObject *)tracefile_tree;
483 #if 0
484 value = lttv_attribute_add(tracefile_tree, LTTV_STATE_PROCESS,
485 LTTV_UINT);
486 *(value.v_uint) = tfcs->process->pid;
487 #endif //0
488 value = lttv_attribute_add(tracefile_tree, LTTV_STATE_EVENT,
489 LTTV_POINTER);
490 /* Only save the position if the tfs has not infinite time. */
491 //if(!g_tree_lookup(self->parent.ts_context->pqueue, &tfcs->parent)
492 // && current_tfcs != tfcs) {
493 if(ltt_time_compare(tfcs->parent.timestamp, ltt_time_infinite) == 0) {
494 *(value.v_pointer) = NULL;
495 } else {
496 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.tf);
497 ep = ltt_event_position_new();
498 ltt_event_position(e, ep);
499 *(value.v_pointer) = ep;
500
501 guint nb_block, offset;
502 guint64 tsc;
503 LttTracefile *tf;
504 ltt_event_position_get(ep, &tf, &nb_block, &offset, &tsc);
505 g_info("Block %u offset %u tsc %llu time %lu.%lu", nb_block, offset,
506 tsc,
507 tfcs->parent.timestamp.tv_sec, tfcs->parent.timestamp.tv_nsec);
508 }
509 }
510 }
511
512
513 static void state_restore(LttvTraceState *self, LttvAttribute *container)
514 {
515 guint i, nb_tracefile, pid, nb_cpus;
516
517 LttvTracefileState *tfcs;
518
519 LttvAttribute *tracefiles_tree, *tracefile_tree;
520
521 guint *running_process;
522
523 LttvAttributeType type;
524
525 LttvAttributeValue value;
526
527 LttvAttributeName name;
528
529 LttEventPosition *ep;
530
531 LttvTracesetContext *tsc = self->parent.ts_context;
532
533 tracefiles_tree = lttv_attribute_find_subdir(container,
534 LTTV_STATE_TRACEFILES);
535
536 type = lttv_attribute_get_by_name(container, LTTV_STATE_PROCESSES,
537 &value);
538 g_assert(type == LTTV_POINTER);
539 lttv_state_free_process_table(self->processes);
540 self->processes = lttv_state_copy_process_table(*(value.v_pointer));
541
542 /* Add the currently running processes array */
543 nb_cpus = ltt_trace_get_num_cpu(self->parent.t);
544 type = lttv_attribute_get_by_name(container, LTTV_STATE_RUNNING_PROCESS,
545 &value);
546 g_assert(type == LTTV_POINTER);
547 running_process = *(value.v_pointer);
548 for(i=0;i<nb_cpus;i++) {
549 pid = running_process[i];
550 self->running_process[i] = lttv_state_find_process(self, i, pid);
551 g_assert(self->running_process[i] != NULL);
552 }
553
554
555 nb_tracefile = self->parent.tracefiles->len;
556
557 g_tree_destroy(tsc->pqueue);
558 tsc->pqueue = g_tree_new(compare_tracefile);
559
560 for(i = 0 ; i < nb_tracefile ; i++) {
561 tfcs =
562 LTTV_TRACEFILE_STATE(g_array_index(self->parent.tracefiles,
563 LttvTracefileContext*, i));
564 type = lttv_attribute_get(tracefiles_tree, i, &name, &value);
565 g_assert(type == LTTV_GOBJECT);
566 tracefile_tree = *((LttvAttribute **)(value.v_gobject));
567 #if 0
568 type = lttv_attribute_get_by_name(tracefile_tree, LTTV_STATE_PROCESS,
569 &value);
570 g_assert(type == LTTV_UINT);
571 pid = *(value.v_uint);
572 tfcs->process = lttv_state_find_process_or_create(tfcs, pid);
573 #endif //0
574 type = lttv_attribute_get_by_name(tracefile_tree, LTTV_STATE_EVENT,
575 &value);
576 g_assert(type == LTTV_POINTER);
577 //g_assert(*(value.v_pointer) != NULL);
578 ep = *(value.v_pointer);
579 g_assert(tfcs->parent.t_context != NULL);
580
581 LttvTracefileContext *tfc = LTTV_TRACEFILE_CONTEXT(tfcs);
582
583 if(ep != NULL) {
584 g_assert(ltt_tracefile_seek_position(tfc->tf, ep) == 0);
585 tfc->timestamp = ltt_event_time(ltt_tracefile_get_event(tfc->tf));
586 g_assert(ltt_time_compare(tfc->timestamp, ltt_time_infinite) != 0);
587 g_tree_insert(tsc->pqueue, tfc, tfc);
588 g_info("Restoring state for a tf at time %lu.%lu", tfc->timestamp.tv_sec, tfc->timestamp.tv_nsec);
589 } else {
590 tfc->timestamp = ltt_time_infinite;
591 }
592 }
593 }
594
595
596 static void state_saved_free(LttvTraceState *self, LttvAttribute *container)
597 {
598 guint i, nb_tracefile, nb_cpus;
599
600 LttvTracefileState *tfcs;
601
602 LttvAttribute *tracefiles_tree, *tracefile_tree;
603
604 guint *running_process;
605
606 LttvAttributeType type;
607
608 LttvAttributeValue value;
609
610 LttvAttributeName name;
611
612 LttEventPosition *ep;
613
614 tracefiles_tree = lttv_attribute_find_subdir(container,
615 LTTV_STATE_TRACEFILES);
616 g_object_ref(G_OBJECT(tracefiles_tree));
617 lttv_attribute_remove_by_name(container, LTTV_STATE_TRACEFILES);
618
619 type = lttv_attribute_get_by_name(container, LTTV_STATE_PROCESSES,
620 &value);
621 g_assert(type == LTTV_POINTER);
622 lttv_state_free_process_table(*(value.v_pointer));
623 *(value.v_pointer) = NULL;
624 lttv_attribute_remove_by_name(container, LTTV_STATE_PROCESSES);
625
626 /* Free running processes array */
627 nb_cpus = ltt_trace_get_num_cpu(self->parent.t);
628 type = lttv_attribute_get_by_name(container, LTTV_STATE_RUNNING_PROCESS,
629 &value);
630 g_assert(type == LTTV_POINTER);
631 running_process = *(value.v_pointer);
632 g_free(running_process);
633
634 nb_tracefile = self->parent.tracefiles->len;
635
636 for(i = 0 ; i < nb_tracefile ; i++) {
637 tfcs =
638 LTTV_TRACEFILE_STATE(g_array_index(self->parent.tracefiles,
639 LttvTracefileContext*, i));
640 type = lttv_attribute_get(tracefiles_tree, i, &name, &value);
641 g_assert(type == LTTV_GOBJECT);
642 tracefile_tree = *((LttvAttribute **)(value.v_gobject));
643
644 type = lttv_attribute_get_by_name(tracefile_tree, LTTV_STATE_EVENT,
645 &value);
646 g_assert(type == LTTV_POINTER);
647 if(*(value.v_pointer) != NULL) g_free(*(value.v_pointer));
648 }
649 g_object_unref(G_OBJECT(tracefiles_tree));
650 }
651
652
653 static void free_saved_state(LttvTraceState *self)
654 {
655 guint i, nb;
656
657 LttvAttributeType type;
658
659 LttvAttributeValue value;
660
661 LttvAttributeName name;
662
663 LttvAttribute *saved_states;
664
665 saved_states = lttv_attribute_find_subdir(self->parent.t_a,
666 LTTV_STATE_SAVED_STATES);
667
668 nb = lttv_attribute_get_number(saved_states);
669 for(i = 0 ; i < nb ; i++) {
670 type = lttv_attribute_get(saved_states, i, &name, &value);
671 g_assert(type == LTTV_GOBJECT);
672 state_saved_free(self, *((LttvAttribute **)value.v_gobject));
673 }
674
675 lttv_attribute_remove_by_name(self->parent.t_a, LTTV_STATE_SAVED_STATES);
676 }
677
678
679 static void
680 create_max_time(LttvTraceState *tcs)
681 {
682 LttvAttributeValue v;
683
684 lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_SAVED_STATES_TIME,
685 LTTV_POINTER, &v);
686 g_assert(*(v.v_pointer) == NULL);
687 *(v.v_pointer) = g_new(LttTime,1);
688 *((LttTime *)*(v.v_pointer)) = ltt_time_zero;
689 }
690
691
692 static void
693 get_max_time(LttvTraceState *tcs)
694 {
695 LttvAttributeValue v;
696
697 lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_SAVED_STATES_TIME,
698 LTTV_POINTER, &v);
699 g_assert(*(v.v_pointer) != NULL);
700 tcs->max_time_state_recomputed_in_seek = (LttTime *)*(v.v_pointer);
701 }
702
703
704 static void
705 free_max_time(LttvTraceState *tcs)
706 {
707 LttvAttributeValue v;
708
709 lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_SAVED_STATES_TIME,
710 LTTV_POINTER, &v);
711 g_free(*(v.v_pointer));
712 *(v.v_pointer) = NULL;
713 }
714
715
716 typedef struct _LttvNameTables {
717 // FIXME GQuark *eventtype_names;
718 GQuark *syscall_names;
719 GQuark *trap_names;
720 GQuark *irq_names;
721 } LttvNameTables;
722
723
724 static void
725 create_name_tables(LttvTraceState *tcs)
726 {
727 int i, nb;
728
729 GQuark f_name, e_name;
730
731 LttvTraceHook h;
732
733 LttvTraceHookByFacility *thf;
734
735 LttEventType *et;
736
737 LttType *t;
738
739 GString *fe_name = g_string_new("");
740
741 LttvNameTables *name_tables = g_new(LttvNameTables, 1);
742
743 LttvAttributeValue v;
744
745 lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_NAME_TABLES,
746 LTTV_POINTER, &v);
747 g_assert(*(v.v_pointer) == NULL);
748 *(v.v_pointer) = name_tables;
749 #if 0 // Use iteration over the facilities_by_name and then list all event
750 // types of each facility
751 nb = ltt_trace_eventtype_number(tcs->parent.t);
752 name_tables->eventtype_names = g_new(GQuark, nb);
753 for(i = 0 ; i < nb ; i++) {
754 et = ltt_trace_eventtype_get(tcs->parent.t, i);
755 e_name = ltt_eventtype_name(et);
756 f_name = ltt_facility_name(ltt_eventtype_facility(et));
757 g_string_printf(fe_name, "%s.%s", f_name, e_name);
758 name_tables->eventtype_names[i] = g_quark_from_string(fe_name->str);
759 }
760 #endif //0
761 if(lttv_trace_find_hook(tcs->parent.t,
762 LTT_FACILITY_KERNEL, LTT_EVENT_SYSCALL_ENTRY,
763 LTT_FIELD_SYSCALL_ID, 0, 0,
764 NULL, NULL, &h))
765 return;
766
767 thf = lttv_trace_hook_get_first(&h);
768
769 t = ltt_field_type(thf->f1);
770 nb = ltt_type_element_number(t);
771
772 lttv_trace_hook_destroy(&h);
773
774 /* CHECK syscalls should be an enum but currently are not!
775 name_tables->syscall_names = g_new(GQuark, nb);
776
777 for(i = 0 ; i < nb ; i++) {
778 name_tables->syscall_names[i] = g_quark_from_string(
779 ltt_enum_string_get(t, i));
780 }
781 */
782
783 name_tables->syscall_names = g_new(GQuark, 256);
784 for(i = 0 ; i < 256 ; i++) {
785 g_string_printf(fe_name, "syscall %d", i);
786 name_tables->syscall_names[i] = g_quark_from_string(fe_name->str);
787 }
788
789 if(lttv_trace_find_hook(tcs->parent.t, LTT_FACILITY_KERNEL,
790 LTT_EVENT_TRAP_ENTRY,
791 LTT_FIELD_TRAP_ID, 0, 0,
792 NULL, NULL, &h))
793 return;
794
795 thf = lttv_trace_hook_get_first(&h);
796
797 t = ltt_field_type(thf->f1);
798 nb = ltt_type_element_number(t);
799
800 lttv_trace_hook_destroy(&h);
801
802 /*
803 name_tables->trap_names = g_new(GQuark, nb);
804 for(i = 0 ; i < nb ; i++) {
805 name_tables->trap_names[i] = g_quark_from_string(
806 ltt_enum_string_get(t, i));
807 }
808 */
809
810 name_tables->trap_names = g_new(GQuark, 256);
811 for(i = 0 ; i < 256 ; i++) {
812 g_string_printf(fe_name, "trap %d", i);
813 name_tables->trap_names[i] = g_quark_from_string(fe_name->str);
814 }
815
816 if(lttv_trace_find_hook(tcs->parent.t,
817 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
818 LTT_FIELD_IRQ_ID, 0, 0,
819 NULL, NULL, &h))
820 return;
821
822 thf = lttv_trace_hook_get_first(&h);
823
824 t = ltt_field_type(thf->f1);
825 nb = ltt_type_element_number(t);
826
827 lttv_trace_hook_destroy(&h);
828
829 /*
830 name_tables->irq_names = g_new(GQuark, nb);
831 for(i = 0 ; i < nb ; i++) {
832 name_tables->irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
833 }
834 */
835
836 name_tables->irq_names = g_new(GQuark, 256);
837 for(i = 0 ; i < 256 ; i++) {
838 g_string_printf(fe_name, "irq %d", i);
839 name_tables->irq_names[i] = g_quark_from_string(fe_name->str);
840 }
841
842 g_string_free(fe_name, TRUE);
843 }
844
845
846 static void
847 get_name_tables(LttvTraceState *tcs)
848 {
849 LttvNameTables *name_tables;
850
851 LttvAttributeValue v;
852
853 lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_NAME_TABLES,
854 LTTV_POINTER, &v);
855 g_assert(*(v.v_pointer) != NULL);
856 name_tables = (LttvNameTables *)*(v.v_pointer);
857 //tcs->eventtype_names = name_tables->eventtype_names;
858 tcs->syscall_names = name_tables->syscall_names;
859 tcs->trap_names = name_tables->trap_names;
860 tcs->irq_names = name_tables->irq_names;
861 }
862
863
864 static void
865 free_name_tables(LttvTraceState *tcs)
866 {
867 LttvNameTables *name_tables;
868
869 LttvAttributeValue v;
870
871 lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_NAME_TABLES,
872 LTTV_POINTER, &v);
873 name_tables = (LttvNameTables *)*(v.v_pointer);
874 *(v.v_pointer) = NULL;
875
876 // g_free(name_tables->eventtype_names);
877 g_free(name_tables->syscall_names);
878 g_free(name_tables->trap_names);
879 g_free(name_tables->irq_names);
880 g_free(name_tables);
881 }
882
883 static void push_state(LttvTracefileState *tfs, LttvExecutionMode t,
884 guint state_id)
885 {
886 LttvExecutionState *es;
887
888 guint cpu = ltt_tracefile_num(tfs->parent.tf);
889 LttvTraceState *ts = (LttvTraceState*)tfs->parent.t_context;
890 LttvProcessState *process = ts->running_process[cpu];
891
892 guint depth = process->execution_stack->len;
893
894 process->execution_stack =
895 g_array_set_size(process->execution_stack, depth + 1);
896 /* Keep in sync */
897 process->state =
898 &g_array_index(process->execution_stack, LttvExecutionState, depth - 1);
899
900 es = &g_array_index(process->execution_stack, LttvExecutionState, depth);
901 es->t = t;
902 es->n = state_id;
903 es->entry = es->change = tfs->parent.timestamp;
904 es->s = process->state->s;
905 process->state = es;
906 }
907
908
909 static void pop_state(LttvTracefileState *tfs, LttvExecutionMode t)
910 {
911 guint cpu = ltt_tracefile_num(tfs->parent.tf);
912 LttvTraceState *ts = (LttvTraceState*)tfs->parent.t_context;
913 LttvProcessState *process = ts->running_process[cpu];
914
915 guint depth = process->execution_stack->len;
916
917 if(process->state->t != t){
918 g_info("Different execution mode type (%lu.%09lu): ignore it\n",
919 tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec);
920 g_info("process state has %s when pop_int is %s\n",
921 g_quark_to_string(process->state->t),
922 g_quark_to_string(t));
923 g_info("{ %u, %u, %s, %s }\n",
924 process->pid,
925 process->ppid,
926 g_quark_to_string(process->name),
927 g_quark_to_string(process->state->s));
928 return;
929 }
930
931 if(depth == 1){
932 g_info("Trying to pop last state on stack (%lu.%09lu): ignore it\n",
933 tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec);
934 return;
935 }
936
937 process->execution_stack =
938 g_array_set_size(process->execution_stack, depth - 1);
939 process->state = &g_array_index(process->execution_stack, LttvExecutionState,
940 depth - 2);
941 process->state->change = tfs->parent.timestamp;
942 }
943
944
945 LttvProcessState *
946 lttv_state_create_process(LttvTraceState *tcs, LttvProcessState *parent,
947 guint cpu, guint pid, const LttTime *timestamp)
948 {
949 LttvProcessState *process = g_new(LttvProcessState, 1);
950
951 LttvExecutionState *es;
952
953 LttvTraceContext *tc = (LttvTraceContext*)tcs;
954
955 char buffer[128];
956
957 process->pid = pid;
958 process->cpu = cpu;
959 //process->last_cpu = tfs->cpu_name;
960 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
961 g_info("Process %u, core %p", process->pid, process);
962 g_hash_table_insert(tcs->processes, process, process);
963
964 if(parent) {
965 process->ppid = parent->pid;
966 process->name = parent->name;
967 process->creation_time = *timestamp;
968 }
969
970 /* No parent. This process exists but we are missing all information about
971 its creation. The birth time is set to zero but we remember the time of
972 insertion */
973
974 else {
975 process->ppid = 0;
976 process->name = LTTV_STATE_UNNAMED;
977 process->creation_time = ltt_time_zero;
978 }
979
980 process->insertion_time = *timestamp;
981 sprintf(buffer,"%d-%lu.%lu",pid, process->creation_time.tv_sec,
982 process->creation_time.tv_nsec);
983 process->pid_time = g_quark_from_string(buffer);
984 process->cpu = cpu;
985 //process->last_cpu = tfs->cpu_name;
986 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
987 process->execution_stack = g_array_sized_new(FALSE, FALSE,
988 sizeof(LttvExecutionState), PREALLOCATED_EXECUTION_STACK);
989 process->execution_stack = g_array_set_size(process->execution_stack, 1);
990 es = process->state = &g_array_index(process->execution_stack,
991 LttvExecutionState, 0);
992 es->t = LTTV_STATE_USER_MODE;
993 es->n = LTTV_STATE_SUBMODE_NONE;
994 es->entry = *timestamp;
995 //g_assert(timestamp->tv_sec != 0);
996 es->change = *timestamp;
997 es->s = LTTV_STATE_WAIT_FORK;
998
999 return process;
1000 }
1001
1002 LttvProcessState *lttv_state_find_process(LttvTraceState *ts, guint cpu,
1003 guint pid)
1004 {
1005 LttvProcessState key;
1006 LttvProcessState *process;
1007
1008 key.pid = pid;
1009 key.cpu = cpu;
1010 process = g_hash_table_lookup(ts->processes, &key);
1011 return process;
1012 }
1013
1014 LttvProcessState *
1015 lttv_state_find_process_or_create(LttvTraceState *ts, guint cpu, guint pid,
1016 LttTime *timestamp)
1017 {
1018 LttvProcessState *process = lttv_state_find_process(ts, cpu, pid);
1019
1020 /* Put ltt_time_zero creation time for unexisting processes */
1021 if(unlikely(process == NULL)) process = lttv_state_create_process(ts,
1022 NULL, cpu, pid, timestamp);
1023 return process;
1024 }
1025
1026 /* FIXME : this function should be called when we receive an event telling that
1027 * release_task has been called in the kernel. In happens generally when
1028 * the parent waits for its child terminaison, but may also happen in special
1029 * cases in the child's exit : when the parent ignores its children SIGCCHLD or
1030 * has the flag SA_NOCLDWAIT. It can also happen when the child is part
1031 * of a killed thread ground, but isn't the leader.
1032 */
1033 static void exit_process(LttvTracefileState *tfs, LttvProcessState *process)
1034 {
1035 LttvTraceState *ts = LTTV_TRACE_STATE(tfs->parent.t_context);
1036 LttvProcessState key;
1037
1038 key.pid = process->pid;
1039 key.cpu = process->cpu;
1040 g_hash_table_remove(ts->processes, &key);
1041 g_array_free(process->execution_stack, TRUE);
1042 g_free(process);
1043 }
1044
1045
1046 static void free_process_state(gpointer key, gpointer value,gpointer user_data)
1047 {
1048 g_array_free(((LttvProcessState *)value)->execution_stack, TRUE);
1049 g_free(value);
1050 }
1051
1052
1053 static void lttv_state_free_process_table(GHashTable *processes)
1054 {
1055 g_hash_table_foreach(processes, free_process_state, NULL);
1056 g_hash_table_destroy(processes);
1057 }
1058
1059
1060 static gboolean syscall_entry(void *hook_data, void *call_data)
1061 {
1062 LttvTracefileState *s = (LttvTracefileState *)call_data;
1063 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
1064 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
1065 LttField *f = thf->f1;
1066
1067 LttvExecutionSubmode submode;
1068
1069 submode = ((LttvTraceState *)(s->parent.t_context))->syscall_names[
1070 ltt_event_get_unsigned(e, f)];
1071 push_state(s, LTTV_STATE_SYSCALL, submode);
1072 return FALSE;
1073 }
1074
1075
1076 static gboolean syscall_exit(void *hook_data, void *call_data)
1077 {
1078 LttvTracefileState *s = (LttvTracefileState *)call_data;
1079
1080 pop_state(s, LTTV_STATE_SYSCALL);
1081 return FALSE;
1082 }
1083
1084
1085 static gboolean trap_entry(void *hook_data, void *call_data)
1086 {
1087 LttvTracefileState *s = (LttvTracefileState *)call_data;
1088 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
1089 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
1090 LttField *f = thf->f1;
1091
1092 LttvExecutionSubmode submode;
1093
1094 submode = ((LttvTraceState *)(s->parent.t_context))->trap_names[
1095 ltt_event_get_unsigned(e, f)];
1096 push_state(s, LTTV_STATE_TRAP, submode);
1097 return FALSE;
1098 }
1099
1100
1101 static gboolean trap_exit(void *hook_data, void *call_data)
1102 {
1103 LttvTracefileState *s = (LttvTracefileState *)call_data;
1104
1105 pop_state(s, LTTV_STATE_TRAP);
1106 return FALSE;
1107 }
1108
1109
1110 static gboolean irq_entry(void *hook_data, void *call_data)
1111 {
1112 LttvTracefileState *s = (LttvTracefileState *)call_data;
1113 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
1114 guint8 fac_id = ltt_event_facility_id(e);
1115 guint8 ev_id = ltt_event_eventtype_id(e);
1116 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
1117 // g_assert(lttv_trace_hook_get_first((LttvTraceHook *)hook_data)->f1 != NULL);
1118 g_assert(thf->f1 != NULL);
1119 // g_assert(thf == lttv_trace_hook_get_first((LttvTraceHook *)hook_data));
1120 LttField *f = thf->f1;
1121
1122 LttvExecutionSubmode submode;
1123
1124 submode = ((LttvTraceState *)(s->parent.t_context))->irq_names[
1125 ltt_event_get_unsigned(e, f)];
1126
1127 /* Do something with the info about being in user or system mode when int? */
1128 push_state(s, LTTV_STATE_IRQ, submode);
1129 return FALSE;
1130 }
1131
1132
1133 static gboolean irq_exit(void *hook_data, void *call_data)
1134 {
1135 LttvTracefileState *s = (LttvTracefileState *)call_data;
1136
1137 pop_state(s, LTTV_STATE_IRQ);
1138 return FALSE;
1139 }
1140
1141
1142 static gboolean schedchange(void *hook_data, void *call_data)
1143 {
1144 LttvTracefileState *s = (LttvTracefileState *)call_data;
1145 guint cpu = ltt_tracefile_num(s->parent.tf);
1146 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
1147 LttvProcessState *process = ts->running_process[cpu];
1148
1149 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
1150 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
1151 guint pid_in, pid_out;
1152 gint state_out;
1153
1154 pid_out = ltt_event_get_unsigned(e, thf->f1);
1155 pid_in = ltt_event_get_unsigned(e, thf->f2);
1156 state_out = ltt_event_get_int(e, thf->f3);
1157
1158 if(likely(process != NULL)) {
1159
1160 /* We could not know but it was not the idle process executing.
1161 This should only happen at the beginning, before the first schedule
1162 event, and when the initial information (current process for each CPU)
1163 is missing. It is not obvious how we could, after the fact, compensate
1164 the wrongly attributed statistics. */
1165
1166 //This test only makes sense once the state is known and if there is no
1167 //missing events.
1168 //if(unlikely(process->pid != pid_out)) {
1169 // g_assert(process->pid == 0);
1170 //}
1171
1172 if(unlikely(process->state->s == LTTV_STATE_EXIT)) {
1173 process->state->s = LTTV_STATE_ZOMBIE;
1174 } else {
1175 if(unlikely(state_out == 0)) process->state->s = LTTV_STATE_WAIT_CPU;
1176 else process->state->s = LTTV_STATE_WAIT;
1177 } /* FIXME : we do not remove process here, because the kernel
1178 * still has them : they may be zombies. We need to know
1179 * exactly when release_task is executed on the PID to
1180 * know when the zombie is destroyed.
1181 */
1182 //else
1183 // exit_process(s, process);
1184
1185 process->state->change = s->parent.timestamp;
1186 }
1187 process = ts->running_process[cpu] =
1188 lttv_state_find_process_or_create(
1189 (LttvTraceState*)s->parent.t_context,
1190 cpu, pid_in,
1191 &s->parent.timestamp);
1192 process->state->s = LTTV_STATE_RUN;
1193 process->cpu = cpu;
1194 // process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)s)->tf);
1195 process->state->change = s->parent.timestamp;
1196 return FALSE;
1197 }
1198
1199 static gboolean process_fork(void *hook_data, void *call_data)
1200 {
1201 LttvTracefileState *s = (LttvTracefileState *)call_data;
1202 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
1203 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
1204 LttField *f;
1205 guint parent_pid;
1206 guint child_pid;
1207 LttvProcessState *zombie_process;
1208 guint cpu = ltt_tracefile_num(s->parent.tf);
1209 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
1210 LttvProcessState *process = ts->running_process[cpu];
1211
1212 /* Parent PID */
1213 f = thf->f1;
1214 parent_pid = ltt_event_get_unsigned(e, f);
1215
1216 /* Child PID */
1217 f = thf->f2;
1218 child_pid = ltt_event_get_unsigned(e, f);
1219
1220 zombie_process = lttv_state_find_process(ts, ANY_CPU, child_pid);
1221
1222 if(unlikely(zombie_process != NULL)) {
1223 /* Reutilisation of PID. Only now we are sure that the old PID
1224 * has been released. FIXME : should know when release_task happens instead.
1225 */
1226 exit_process(s, zombie_process);
1227 }
1228 g_assert(process->pid != child_pid);
1229 // FIXME : Add this test in the "known state" section
1230 // g_assert(process->pid == parent_pid);
1231 lttv_state_create_process(ts, process, cpu, child_pid, &s->parent.timestamp);
1232
1233 return FALSE;
1234 }
1235
1236
1237 static gboolean process_exit(void *hook_data, void *call_data)
1238 {
1239 LttvTracefileState *s = (LttvTracefileState *)call_data;
1240 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
1241 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
1242 LttField *f;
1243 guint pid;
1244 guint cpu = ltt_tracefile_num(s->parent.tf);
1245 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
1246 LttvProcessState *process = ts->running_process[cpu];
1247
1248 pid = ltt_event_get_unsigned(e, thf->f1);
1249
1250 // FIXME : Add this test in the "known state" section
1251 // g_assert(process->pid == pid);
1252
1253 if(likely(process != NULL)) {
1254 process->state->s = LTTV_STATE_EXIT;
1255 }
1256 return FALSE;
1257 }
1258
1259 static gboolean process_free(void *hook_data, void *call_data)
1260 {
1261 LttvTracefileState *s = (LttvTracefileState *)call_data;
1262 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
1263 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
1264 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
1265 guint release_pid;
1266 LttvProcessState *process;
1267
1268 /* PID of the process to release */
1269 release_pid = ltt_event_get_unsigned(e, thf->f1);
1270
1271 process = lttv_state_find_process(ts, ANY_CPU, release_pid);
1272
1273 if(likely(process != NULL)) {
1274 /* release_task is happening at kernel level : we can now safely release
1275 * the data structure of the process */
1276 exit_process(s, process);
1277 }
1278
1279 return FALSE;
1280 }
1281
1282 gint lttv_state_hook_add_event_hooks(void *hook_data, void *call_data)
1283 {
1284 LttvTracesetState *tss = (LttvTracesetState*)(call_data);
1285
1286 lttv_state_add_event_hooks(tss);
1287
1288 return 0;
1289 }
1290
1291 void lttv_state_add_event_hooks(LttvTracesetState *self)
1292 {
1293 LttvTraceset *traceset = self->parent.ts;
1294
1295 guint i, j, k, l, nb_trace, nb_tracefile;
1296
1297 LttvTraceState *ts;
1298
1299 LttvTracefileState *tfs;
1300
1301 GArray *hooks;
1302
1303 LttvTraceHookByFacility *thf;
1304
1305 LttvTraceHook *hook;
1306
1307 LttvAttributeValue val;
1308
1309 gint ret;
1310
1311 nb_trace = lttv_traceset_number(traceset);
1312 for(i = 0 ; i < nb_trace ; i++) {
1313 ts = (LttvTraceState *)self->parent.traces[i];
1314
1315 /* Find the eventtype id for the following events and register the
1316 associated by id hooks. */
1317
1318 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 10);
1319 hooks = g_array_set_size(hooks, 10);
1320
1321 ret = lttv_trace_find_hook(ts->parent.t,
1322 LTT_FACILITY_KERNEL, LTT_EVENT_SYSCALL_ENTRY,
1323 LTT_FIELD_SYSCALL_ID, 0, 0,
1324 syscall_entry, NULL, &g_array_index(hooks, LttvTraceHook, 0));
1325 g_assert(!ret);
1326
1327 ret = lttv_trace_find_hook(ts->parent.t,
1328 LTT_FACILITY_KERNEL, LTT_EVENT_SYSCALL_EXIT,
1329 0, 0, 0,
1330 syscall_exit, NULL, &g_array_index(hooks, LttvTraceHook, 1));
1331 g_assert(!ret);
1332
1333 ret = lttv_trace_find_hook(ts->parent.t,
1334 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY,
1335 LTT_FIELD_TRAP_ID, 0, 0,
1336 trap_entry, NULL, &g_array_index(hooks, LttvTraceHook, 2));
1337 g_assert(!ret);
1338
1339 ret = lttv_trace_find_hook(ts->parent.t,
1340 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT,
1341 0, 0, 0,
1342 trap_exit, NULL, &g_array_index(hooks, LttvTraceHook, 3));
1343 g_assert(!ret);
1344
1345 ret = lttv_trace_find_hook(ts->parent.t,
1346 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
1347 LTT_FIELD_IRQ_ID, 0, 0,
1348 irq_entry, NULL, &g_array_index(hooks, LttvTraceHook, 4));
1349 g_assert(!ret);
1350
1351 ret = lttv_trace_find_hook(ts->parent.t,
1352 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
1353 0, 0, 0,
1354 irq_exit, NULL, &g_array_index(hooks, LttvTraceHook, 5));
1355 g_assert(!ret);
1356
1357 ret = lttv_trace_find_hook(ts->parent.t,
1358 LTT_FACILITY_PROCESS, LTT_EVENT_SCHEDCHANGE,
1359 LTT_FIELD_OUT, LTT_FIELD_IN, LTT_FIELD_OUT_STATE,
1360 schedchange, NULL, &g_array_index(hooks, LttvTraceHook, 6));
1361 g_assert(!ret);
1362
1363 ret = lttv_trace_find_hook(ts->parent.t,
1364 LTT_FACILITY_PROCESS, LTT_EVENT_FORK,
1365 LTT_FIELD_PARENT_PID, LTT_FIELD_CHILD_PID, 0,
1366 process_fork, NULL, &g_array_index(hooks, LttvTraceHook, 7));
1367 g_assert(!ret);
1368
1369 ret = lttv_trace_find_hook(ts->parent.t,
1370 LTT_FACILITY_PROCESS, LTT_EVENT_EXIT,
1371 LTT_FIELD_PID, 0, 0,
1372 process_exit, NULL, &g_array_index(hooks, LttvTraceHook, 8));
1373 g_assert(!ret);
1374
1375 ret = lttv_trace_find_hook(ts->parent.t,
1376 LTT_FACILITY_PROCESS, LTT_EVENT_FREE,
1377 LTT_FIELD_PID, 0, 0,
1378 process_free, NULL, &g_array_index(hooks, LttvTraceHook, 9));
1379 g_assert(!ret);
1380
1381
1382 /* Add these hooks to each event_by_id hooks list */
1383
1384 nb_tracefile = ts->parent.tracefiles->len;
1385
1386 for(j = 0 ; j < nb_tracefile ; j++) {
1387 tfs =
1388 LTTV_TRACEFILE_STATE(g_array_index(ts->parent.tracefiles,
1389 LttvTracefileContext*, j));
1390
1391 for(k = 0 ; k < hooks->len ; k++) {
1392 hook = &g_array_index(hooks, LttvTraceHook, k);
1393 for(l=0;l<hook->fac_list->len;l++) {
1394 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1395 lttv_hooks_add(
1396 lttv_hooks_by_id_find(tfs->parent.event_by_id, thf->id),
1397 thf->h,
1398 thf,
1399 LTTV_PRIO_STATE);
1400 }
1401 }
1402 }
1403 lttv_attribute_find(self->parent.a, LTTV_STATE_HOOKS, LTTV_POINTER, &val);
1404 *(val.v_pointer) = hooks;
1405 }
1406 }
1407
1408 gint lttv_state_hook_remove_event_hooks(void *hook_data, void *call_data)
1409 {
1410 LttvTracesetState *tss = (LttvTracesetState*)(call_data);
1411
1412 lttv_state_remove_event_hooks(tss);
1413
1414 return 0;
1415 }
1416
1417 static guint test_event_count = 0;
1418 void lttv_state_remove_event_hooks(LttvTracesetState *self)
1419 {
1420 LttvTraceset *traceset = self->parent.ts;
1421
1422 guint i, j, k, l, nb_trace, nb_tracefile;
1423
1424 LttvTraceState *ts;
1425
1426 LttvTracefileState *tfs;
1427
1428 GArray *hooks;
1429
1430 LttvTraceHook *hook;
1431
1432 LttvTraceHookByFacility *thf;
1433
1434 LttvAttributeValue val;
1435
1436 nb_trace = lttv_traceset_number(traceset);
1437 for(i = 0 ; i < nb_trace ; i++) {
1438 ts = LTTV_TRACE_STATE(self->parent.traces[i]);
1439 lttv_attribute_find(self->parent.a, LTTV_STATE_HOOKS, LTTV_POINTER, &val);
1440 hooks = *(val.v_pointer);
1441
1442 /* Remove these hooks from each event_by_id hooks list */
1443
1444 nb_tracefile = ts->parent.tracefiles->len;
1445
1446 for(j = 0 ; j < nb_tracefile ; j++) {
1447 tfs =
1448 LTTV_TRACEFILE_STATE(g_array_index(ts->parent.tracefiles,
1449 LttvTracefileContext*, j));
1450
1451 for(k = 0 ; k < hooks->len ; k++) {
1452 hook = &g_array_index(hooks, LttvTraceHook, k);
1453 for(l=0;l<hook->fac_list->len;l++) {
1454 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1455
1456 lttv_hooks_remove_data(
1457 lttv_hooks_by_id_find(tfs->parent.event_by_id, thf->id),
1458 thf->h,
1459 thf);
1460 }
1461 }
1462 }
1463 for(k = 0 ; k < hooks->len ; k++)
1464 lttv_trace_hook_destroy(&g_array_index(hooks, LttvTraceHook, k));
1465 g_array_free(hooks, TRUE);
1466 }
1467 g_info("EVENT COUNT TEST : %u", test_event_count);
1468 }
1469
1470 static gboolean state_save_event_hook(void *hook_data, void *call_data)
1471 {
1472 guint *event_count = (guint*)hook_data;
1473
1474 test_event_count++;
1475 /* Only save at LTTV_STATE_SAVE_INTERVAL */
1476 if(likely((*event_count)++ < LTTV_STATE_SAVE_INTERVAL))
1477 return FALSE;
1478 else
1479 *event_count = 0;
1480
1481 LttvTracefileState *self = (LttvTracefileState *)call_data;
1482
1483 LttvTracefileState *tfcs;
1484
1485 LttvTraceState *tcs = (LttvTraceState *)(self->parent.t_context);
1486
1487 LttEventPosition *ep;
1488
1489 guint i;
1490
1491 LttTracefile *tf;
1492
1493 LttvAttribute *saved_states_tree, *saved_state_tree;
1494
1495 LttvAttributeValue value;
1496
1497 saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a,
1498 LTTV_STATE_SAVED_STATES);
1499 saved_state_tree = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
1500 value = lttv_attribute_add(saved_states_tree,
1501 lttv_attribute_get_number(saved_states_tree), LTTV_GOBJECT);
1502 *(value.v_gobject) = (GObject *)saved_state_tree;
1503 value = lttv_attribute_add(saved_state_tree, LTTV_STATE_TIME, LTTV_TIME);
1504 *(value.v_time) = self->parent.timestamp;
1505 lttv_state_save(tcs, saved_state_tree);
1506 g_debug("Saving state at time %lu.%lu", self->parent.timestamp.tv_sec,
1507 self->parent.timestamp.tv_nsec);
1508
1509 *(tcs->max_time_state_recomputed_in_seek) = self->parent.timestamp;
1510
1511 return FALSE;
1512 }
1513
1514 #if 0
1515 static gboolean block_start(void *hook_data, void *call_data)
1516 {
1517 LttvTracefileState *self = (LttvTracefileState *)call_data;
1518
1519 LttvTracefileState *tfcs;
1520
1521 LttvTraceState *tcs = (LttvTraceState *)(self->parent.t_context);
1522
1523 LttEventPosition *ep;
1524
1525 guint i, nb_block, nb_event, nb_tracefile;
1526
1527 LttTracefile *tf;
1528
1529 LttvAttribute *saved_states_tree, *saved_state_tree;
1530
1531 LttvAttributeValue value;
1532
1533 ep = ltt_event_position_new();
1534
1535 nb_tracefile = tcs->parent.tracefiles->len;
1536
1537 /* Count the number of events added since the last block end in any
1538 tracefile. */
1539
1540 for(i = 0 ; i < nb_tracefile ; i++) {
1541 tfcs =
1542 LTTV_TRACEFILE_STATE(&g_array_index(tcs->parent.tracefiles,
1543 LttvTracefileContext, i));
1544 ltt_event_position(tfcs->parent.e, ep);
1545 ltt_event_position_get(ep, &nb_block, &nb_event, &tf);
1546 tcs->nb_event += nb_event - tfcs->saved_position;
1547 tfcs->saved_position = nb_event;
1548 }
1549 g_free(ep);
1550
1551 if(tcs->nb_event >= tcs->save_interval) {
1552 saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a,
1553 LTTV_STATE_SAVED_STATES);
1554 saved_state_tree = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
1555 value = lttv_attribute_add(saved_states_tree,
1556 lttv_attribute_get_number(saved_states_tree), LTTV_GOBJECT);
1557 *(value.v_gobject) = (GObject *)saved_state_tree;
1558 value = lttv_attribute_add(saved_state_tree, LTTV_STATE_TIME, LTTV_TIME);
1559 *(value.v_time) = self->parent.timestamp;
1560 lttv_state_save(tcs, saved_state_tree);
1561 tcs->nb_event = 0;
1562 g_debug("Saving state at time %lu.%lu", self->parent.timestamp.tv_sec,
1563 self->parent.timestamp.tv_nsec);
1564 }
1565 *(tcs->max_time_state_recomputed_in_seek) = self->parent.timestamp;
1566 return FALSE;
1567 }
1568 #endif //0
1569
1570 #if 0
1571 static gboolean block_end(void *hook_data, void *call_data)
1572 {
1573 LttvTracefileState *self = (LttvTracefileState *)call_data;
1574
1575 LttvTraceState *tcs = (LttvTraceState *)(self->parent.t_context);
1576
1577 LttTracefile *tf;
1578
1579 LttEventPosition *ep;
1580
1581 guint nb_block, nb_event;
1582
1583 ep = ltt_event_position_new();
1584 ltt_event_position(self->parent.e, ep);
1585 ltt_event_position_get(ep, &nb_block, &nb_event, &tf);
1586 tcs->nb_event += nb_event - self->saved_position + 1;
1587 self->saved_position = 0;
1588 *(tcs->max_time_state_recomputed_in_seek) = self->parent.timestamp;
1589 g_free(ep);
1590
1591 return FALSE;
1592 }
1593 #endif //0
1594 #if 0
1595 void lttv_state_save_add_event_hooks(LttvTracesetState *self)
1596 {
1597 LttvTraceset *traceset = self->parent.ts;
1598
1599 guint i, j, nb_trace, nb_tracefile;
1600
1601 LttvTraceState *ts;
1602
1603 LttvTracefileState *tfs;
1604
1605 LttvTraceHook hook_start, hook_end;
1606
1607 nb_trace = lttv_traceset_number(traceset);
1608 for(i = 0 ; i < nb_trace ; i++) {
1609 ts = (LttvTraceState *)self->parent.traces[i];
1610
1611 lttv_trace_find_hook(ts->parent.t, "core","block_start",NULL,
1612 NULL, NULL, block_start, &hook_start);
1613 lttv_trace_find_hook(ts->parent.t, "core","block_end",NULL,
1614 NULL, NULL, block_end, &hook_end);
1615
1616 nb_tracefile = ts->parent.tracefiles->len;
1617
1618 for(j = 0 ; j < nb_tracefile ; j++) {
1619 tfs =
1620 LTTV_TRACEFILE_STATE(&g_array_index(ts->parent.tracefiles,
1621 LttvTracefileContext, j));
1622 lttv_hooks_add(lttv_hooks_by_id_find(tfs->parent.event_by_id,
1623 hook_start.id), hook_start.h, NULL, LTTV_PRIO_STATE);
1624 lttv_hooks_add(lttv_hooks_by_id_find(tfs->parent.event_by_id,
1625 hook_end.id), hook_end.h, NULL, LTTV_PRIO_STATE);
1626 }
1627 }
1628 }
1629 #endif //0
1630
1631 void lttv_state_save_add_event_hooks(LttvTracesetState *self)
1632 {
1633 LttvTraceset *traceset = self->parent.ts;
1634
1635 guint i, j, nb_trace, nb_tracefile;
1636
1637 LttvTraceState *ts;
1638
1639 LttvTracefileState *tfs;
1640
1641
1642 nb_trace = lttv_traceset_number(traceset);
1643 for(i = 0 ; i < nb_trace ; i++) {
1644
1645 ts = (LttvTraceState *)self->parent.traces[i];
1646 nb_tracefile = ts->parent.tracefiles->len;
1647
1648 guint *event_count = g_new(guint, 1);
1649 *event_count = 0;
1650
1651 for(j = 0 ; j < nb_tracefile ; j++) {
1652 tfs =
1653 LTTV_TRACEFILE_STATE(g_array_index(ts->parent.tracefiles,
1654 LttvTracefileContext*, j));
1655 lttv_hooks_add(tfs->parent.event,
1656 state_save_event_hook,
1657 event_count,
1658 LTTV_PRIO_STATE);
1659
1660 }
1661 }
1662 }
1663
1664 gint lttv_state_save_hook_add_event_hooks(void *hook_data, void *call_data)
1665 {
1666 LttvTracesetState *tss = (LttvTracesetState*)(call_data);
1667
1668 lttv_state_save_add_event_hooks(tss);
1669
1670 return 0;
1671 }
1672
1673
1674 #if 0
1675 void lttv_state_save_remove_event_hooks(LttvTracesetState *self)
1676 {
1677 LttvTraceset *traceset = self->parent.ts;
1678
1679 guint i, j, nb_trace, nb_tracefile;
1680
1681 LttvTraceState *ts;
1682
1683 LttvTracefileState *tfs;
1684
1685 LttvTraceHook hook_start, hook_end;
1686
1687 nb_trace = lttv_traceset_number(traceset);
1688 for(i = 0 ; i < nb_trace ; i++) {
1689 ts = LTTV_TRACE_STATE(self->parent.traces[i]);
1690
1691 lttv_trace_find_hook(ts->parent.t, "core","block_start",NULL,
1692 NULL, NULL, block_start, &hook_start);
1693
1694 lttv_trace_find_hook(ts->parent.t, "core","block_end",NULL,
1695 NULL, NULL, block_end, &hook_end);
1696
1697 nb_tracefile = ts->parent.tracefiles->len;
1698
1699 for(j = 0 ; j < nb_tracefile ; j++) {
1700 tfs =
1701 LTTV_TRACEFILE_STATE(&g_array_index(ts->parent.tracefiles,
1702 LttvTracefileContext, j));
1703 lttv_hooks_remove_data(lttv_hooks_by_id_find(
1704 tfs->parent.event_by_id, hook_start.id), hook_start.h, NULL);
1705 lttv_hooks_remove_data(lttv_hooks_by_id_find(
1706 tfs->parent.event_by_id, hook_end.id), hook_end.h, NULL);
1707 }
1708 }
1709 }
1710 #endif //0
1711
1712 void lttv_state_save_remove_event_hooks(LttvTracesetState *self)
1713 {
1714 LttvTraceset *traceset = self->parent.ts;
1715
1716 guint i, j, nb_trace, nb_tracefile;
1717
1718 LttvTraceState *ts;
1719
1720 LttvTracefileState *tfs;
1721
1722
1723 nb_trace = lttv_traceset_number(traceset);
1724 for(i = 0 ; i < nb_trace ; i++) {
1725
1726 ts = (LttvTraceState *)self->parent.traces[i];
1727 nb_tracefile = ts->parent.tracefiles->len;
1728
1729 guint *event_count;
1730
1731 for(j = 0 ; j < nb_tracefile ; j++) {
1732 tfs =
1733 LTTV_TRACEFILE_STATE(g_array_index(ts->parent.tracefiles,
1734 LttvTracefileContext*, j));
1735 event_count = lttv_hooks_remove(tfs->parent.event,
1736 state_save_event_hook);
1737
1738 }
1739 g_free(event_count);
1740 }
1741 }
1742
1743 gint lttv_state_save_hook_remove_event_hooks(void *hook_data, void *call_data)
1744 {
1745 LttvTracesetState *tss = (LttvTracesetState*)(call_data);
1746
1747 lttv_state_save_remove_event_hooks(tss);
1748
1749 return 0;
1750 }
1751
1752 void lttv_state_traceset_seek_time_closest(LttvTracesetState *self, LttTime t)
1753 {
1754 LttvTraceset *traceset = self->parent.ts;
1755
1756 guint i, nb_trace;
1757
1758 int min_pos, mid_pos, max_pos;
1759
1760 guint call_rest = 0;
1761
1762 LttvTraceState *tcs;
1763
1764 LttvAttributeValue value;
1765
1766 LttvAttributeType type;
1767
1768 LttvAttributeName name;
1769
1770 LttvAttribute *saved_states_tree, *saved_state_tree, *closest_tree;
1771
1772 g_tree_destroy(self->parent.pqueue);
1773 self->parent.pqueue = g_tree_new(compare_tracefile);
1774
1775 g_info("Entering seek_time_closest for time %lu.%lu", t.tv_sec, t.tv_nsec);
1776
1777 nb_trace = lttv_traceset_number(traceset);
1778 for(i = 0 ; i < nb_trace ; i++) {
1779 tcs = (LttvTraceState *)self->parent.traces[i];
1780
1781 if(ltt_time_compare(t, *(tcs->max_time_state_recomputed_in_seek)) < 0) {
1782 saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a,
1783 LTTV_STATE_SAVED_STATES);
1784 min_pos = -1;
1785
1786 if(saved_states_tree) {
1787 max_pos = lttv_attribute_get_number(saved_states_tree) - 1;
1788 mid_pos = max_pos / 2;
1789 while(min_pos < max_pos) {
1790 type = lttv_attribute_get(saved_states_tree, mid_pos, &name, &value);
1791 g_assert(type == LTTV_GOBJECT);
1792 saved_state_tree = *((LttvAttribute **)(value.v_gobject));
1793 type = lttv_attribute_get_by_name(saved_state_tree, LTTV_STATE_TIME,
1794 &value);
1795 g_assert(type == LTTV_TIME);
1796 if(ltt_time_compare(*(value.v_time), t) < 0) {
1797 min_pos = mid_pos;
1798 closest_tree = saved_state_tree;
1799 }
1800 else max_pos = mid_pos - 1;
1801
1802 mid_pos = (min_pos + max_pos + 1) / 2;
1803 }
1804 }
1805
1806 /* restore the closest earlier saved state */
1807 if(min_pos != -1) {
1808 lttv_state_restore(tcs, closest_tree);
1809 call_rest = 1;
1810 }
1811
1812 /* There is no saved state, yet we want to have it. Restart at T0 */
1813 else {
1814 restore_init_state(tcs);
1815 lttv_process_trace_seek_time(&(tcs->parent), ltt_time_zero);
1816 }
1817 }
1818 /* We want to seek quickly without restoring/updating the state */
1819 else {
1820 restore_init_state(tcs);
1821 lttv_process_trace_seek_time(&(tcs->parent), t);
1822 }
1823 }
1824 if(!call_rest) g_info("NOT Calling restore");
1825 }
1826
1827
1828 static void
1829 traceset_state_instance_init (GTypeInstance *instance, gpointer g_class)
1830 {
1831 }
1832
1833
1834 static void
1835 traceset_state_finalize (LttvTracesetState *self)
1836 {
1837 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))->
1838 finalize(G_OBJECT(self));
1839 }
1840
1841
1842 static void
1843 traceset_state_class_init (LttvTracesetContextClass *klass)
1844 {
1845 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
1846
1847 gobject_class->finalize = (void (*)(GObject *self)) traceset_state_finalize;
1848 klass->init = (void (*)(LttvTracesetContext *self, LttvTraceset *ts))init;
1849 klass->fini = (void (*)(LttvTracesetContext *self))fini;
1850 klass->new_traceset_context = new_traceset_context;
1851 klass->new_trace_context = new_trace_context;
1852 klass->new_tracefile_context = new_tracefile_context;
1853 }
1854
1855
1856 GType
1857 lttv_traceset_state_get_type(void)
1858 {
1859 static GType type = 0;
1860 if (type == 0) {
1861 static const GTypeInfo info = {
1862 sizeof (LttvTracesetStateClass),
1863 NULL, /* base_init */
1864 NULL, /* base_finalize */
1865 (GClassInitFunc) traceset_state_class_init, /* class_init */
1866 NULL, /* class_finalize */
1867 NULL, /* class_data */
1868 sizeof (LttvTracesetState),
1869 0, /* n_preallocs */
1870 (GInstanceInitFunc) traceset_state_instance_init, /* instance_init */
1871 NULL /* value handling */
1872 };
1873
1874 type = g_type_register_static (LTTV_TRACESET_CONTEXT_TYPE, "LttvTracesetStateType",
1875 &info, 0);
1876 }
1877 return type;
1878 }
1879
1880
1881 static void
1882 trace_state_instance_init (GTypeInstance *instance, gpointer g_class)
1883 {
1884 }
1885
1886
1887 static void
1888 trace_state_finalize (LttvTraceState *self)
1889 {
1890 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_CONTEXT_TYPE))->
1891 finalize(G_OBJECT(self));
1892 }
1893
1894
1895 static void
1896 trace_state_class_init (LttvTraceStateClass *klass)
1897 {
1898 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
1899
1900 gobject_class->finalize = (void (*)(GObject *self)) trace_state_finalize;
1901 klass->state_save = state_save;
1902 klass->state_restore = state_restore;
1903 klass->state_saved_free = state_saved_free;
1904 }
1905
1906
1907 GType
1908 lttv_trace_state_get_type(void)
1909 {
1910 static GType type = 0;
1911 if (type == 0) {
1912 static const GTypeInfo info = {
1913 sizeof (LttvTraceStateClass),
1914 NULL, /* base_init */
1915 NULL, /* base_finalize */
1916 (GClassInitFunc) trace_state_class_init, /* class_init */
1917 NULL, /* class_finalize */
1918 NULL, /* class_data */
1919 sizeof (LttvTraceState),
1920 0, /* n_preallocs */
1921 (GInstanceInitFunc) trace_state_instance_init, /* instance_init */
1922 NULL /* value handling */
1923 };
1924
1925 type = g_type_register_static (LTTV_TRACE_CONTEXT_TYPE,
1926 "LttvTraceStateType", &info, 0);
1927 }
1928 return type;
1929 }
1930
1931
1932 static void
1933 tracefile_state_instance_init (GTypeInstance *instance, gpointer g_class)
1934 {
1935 }
1936
1937
1938 static void
1939 tracefile_state_finalize (LttvTracefileState *self)
1940 {
1941 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_CONTEXT_TYPE))->
1942 finalize(G_OBJECT(self));
1943 }
1944
1945
1946 static void
1947 tracefile_state_class_init (LttvTracefileStateClass *klass)
1948 {
1949 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
1950
1951 gobject_class->finalize = (void (*)(GObject *self)) tracefile_state_finalize;
1952 }
1953
1954
1955 GType
1956 lttv_tracefile_state_get_type(void)
1957 {
1958 static GType type = 0;
1959 if (type == 0) {
1960 static const GTypeInfo info = {
1961 sizeof (LttvTracefileStateClass),
1962 NULL, /* base_init */
1963 NULL, /* base_finalize */
1964 (GClassInitFunc) tracefile_state_class_init, /* class_init */
1965 NULL, /* class_finalize */
1966 NULL, /* class_data */
1967 sizeof (LttvTracefileState),
1968 0, /* n_preallocs */
1969 (GInstanceInitFunc) tracefile_state_instance_init, /* instance_init */
1970 NULL /* value handling */
1971 };
1972
1973 type = g_type_register_static (LTTV_TRACEFILE_CONTEXT_TYPE,
1974 "LttvTracefileStateType", &info, 0);
1975 }
1976 return type;
1977 }
1978
1979
1980 static void module_init()
1981 {
1982 LTTV_STATE_UNNAMED = g_quark_from_string("unnamed");
1983 LTTV_STATE_MODE_UNKNOWN = g_quark_from_string("unknown execution mode");
1984 LTTV_STATE_USER_MODE = g_quark_from_string("user mode");
1985 LTTV_STATE_WAIT_FORK = g_quark_from_string("wait fork");
1986 LTTV_STATE_SYSCALL = g_quark_from_string("system call");
1987 LTTV_STATE_TRAP = g_quark_from_string("trap");
1988 LTTV_STATE_IRQ = g_quark_from_string("irq");
1989 LTTV_STATE_SUBMODE_UNKNOWN = g_quark_from_string("unknown submode");
1990 LTTV_STATE_SUBMODE_NONE = g_quark_from_string("(no submode)");
1991 LTTV_STATE_WAIT_CPU = g_quark_from_string("wait for cpu");
1992 LTTV_STATE_EXIT = g_quark_from_string("exiting");
1993 LTTV_STATE_ZOMBIE = g_quark_from_string("zombie");
1994 LTTV_STATE_WAIT = g_quark_from_string("wait for I/O");
1995 LTTV_STATE_RUN = g_quark_from_string("running");
1996 LTTV_STATE_TRACEFILES = g_quark_from_string("tracefiles");
1997 LTTV_STATE_PROCESSES = g_quark_from_string("processes");
1998 LTTV_STATE_PROCESS = g_quark_from_string("process");
1999 LTTV_STATE_RUNNING_PROCESS = g_quark_from_string("running_process");
2000 LTTV_STATE_EVENT = g_quark_from_string("event");
2001 LTTV_STATE_SAVED_STATES = g_quark_from_string("saved states");
2002 LTTV_STATE_SAVED_STATES_TIME = g_quark_from_string("saved states time");
2003 LTTV_STATE_TIME = g_quark_from_string("time");
2004 LTTV_STATE_HOOKS = g_quark_from_string("saved state hooks");
2005 LTTV_STATE_NAME_TABLES = g_quark_from_string("name tables");
2006 LTTV_STATE_TRACE_STATE_USE_COUNT =
2007 g_quark_from_string("trace_state_use_count");
2008
2009
2010 LTT_FACILITY_KERNEL = g_quark_from_string("kernel");
2011 LTT_FACILITY_PROCESS = g_quark_from_string("process");
2012
2013
2014 LTT_EVENT_SYSCALL_ENTRY = g_quark_from_string("syscall_entry");
2015 LTT_EVENT_SYSCALL_EXIT = g_quark_from_string("syscall_exit");
2016 LTT_EVENT_TRAP_ENTRY = g_quark_from_string("trap_entry");
2017 LTT_EVENT_TRAP_EXIT = g_quark_from_string("trap_exit");
2018 LTT_EVENT_IRQ_ENTRY = g_quark_from_string("irq_entry");
2019 LTT_EVENT_IRQ_EXIT = g_quark_from_string("irq_exit");
2020 LTT_EVENT_SCHEDCHANGE = g_quark_from_string("schedchange");
2021 LTT_EVENT_FORK = g_quark_from_string("fork");
2022 LTT_EVENT_EXIT = g_quark_from_string("exit");
2023 LTT_EVENT_FREE = g_quark_from_string("free");
2024
2025
2026 LTT_FIELD_SYSCALL_ID = g_quark_from_string("syscall_id");
2027 LTT_FIELD_TRAP_ID = g_quark_from_string("trap_id");
2028 LTT_FIELD_IRQ_ID = g_quark_from_string("irq_id");
2029 LTT_FIELD_OUT = g_quark_from_string("out");
2030 LTT_FIELD_IN = g_quark_from_string("in");
2031 LTT_FIELD_OUT_STATE = g_quark_from_string("out_state");
2032 LTT_FIELD_PARENT_PID = g_quark_from_string("parent_pid");
2033 LTT_FIELD_CHILD_PID = g_quark_from_string("child_pid");
2034 LTT_FIELD_PID = g_quark_from_string("pid");
2035
2036 }
2037
2038 static void module_destroy()
2039 {
2040 }
2041
2042
2043 LTTV_MODULE("state", "State computation", \
2044 "Update the system state, possibly saving it at intervals", \
2045 module_init, module_destroy)
2046
2047
2048
This page took 0.072359 seconds and 4 git commands to generate.