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