mega fix for states : per cpu and _not_ per tracefile state. We have many tracefiles...
[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
472 nb_tracefile = self->parent.tracefiles->len;
473
474 for(i = 0 ; i < nb_tracefile ; i++) {
475 tfcs =
476 LTTV_TRACEFILE_STATE(g_array_index(self->parent.tracefiles,
477 LttvTracefileContext*, i));
478 tracefile_tree = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
479 value = lttv_attribute_add(tracefiles_tree, i,
480 LTTV_GOBJECT);
481 *(value.v_gobject) = (GObject *)tracefile_tree;
482 #if 0
483 value = lttv_attribute_add(tracefile_tree, LTTV_STATE_PROCESS,
484 LTTV_UINT);
485 *(value.v_uint) = tfcs->process->pid;
486 #endif //0
487 value = lttv_attribute_add(tracefile_tree, LTTV_STATE_EVENT,
488 LTTV_POINTER);
489 /* Only save the position if the tfs has not infinite time. */
490 //if(!g_tree_lookup(self->parent.ts_context->pqueue, &tfcs->parent)
491 // && current_tfcs != tfcs) {
492 if(ltt_time_compare(tfcs->parent.timestamp, ltt_time_infinite) == 0) {
493 *(value.v_pointer) = NULL;
494 } else {
495 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.tf);
496 ep = ltt_event_position_new();
497 ltt_event_position(e, ep);
498 *(value.v_pointer) = ep;
499
500 guint nb_block, offset;
501 guint64 tsc;
502 LttTracefile *tf;
503 ltt_event_position_get(ep, &tf, &nb_block, &offset, &tsc);
504 g_debug("Block %u offset %u tsc %llu time %lu.%lu", nb_block, offset,
505 tsc,
506 tfcs->parent.timestamp.tv_sec, tfcs->parent.timestamp.tv_nsec);
507 }
508 }
509 }
510
511
512 static void state_restore(LttvTraceState *self, LttvAttribute *container)
513 {
514 guint i, nb_tracefile, pid, nb_cpus;
515
516 LttvTracefileState *tfcs;
517
518 LttvAttribute *tracefiles_tree, *tracefile_tree;
519
520 guint *running_process;
521
522 LttvAttributeType type;
523
524 LttvAttributeValue value;
525
526 LttvAttributeName name;
527
528 LttEventPosition *ep;
529
530 LttvTracesetContext *tsc = self->parent.ts_context;
531
532 tracefiles_tree = lttv_attribute_find_subdir(container,
533 LTTV_STATE_TRACEFILES);
534
535 type = lttv_attribute_get_by_name(container, LTTV_STATE_PROCESSES,
536 &value);
537 g_assert(type == LTTV_POINTER);
538 lttv_state_free_process_table(self->processes);
539 self->processes = lttv_state_copy_process_table(*(value.v_pointer));
540
541 /* Add the currently running processes array */
542 nb_cpus = ltt_trace_get_num_cpu(self->parent.t);
543 type = lttv_attribute_get_by_name(container, LTTV_STATE_RUNNING_PROCESS,
544 &value);
545 g_assert(type == LTTV_POINTER);
546 running_process = *(value.v_pointer);
547 for(i=0;i<nb_cpus;i++) {
548 pid = running_process[i];
549 self->running_process[i] = lttv_state_find_process(self, i, pid);
550 g_assert(self->running_process[i] != NULL);
551 }
552
553
554 nb_tracefile = self->parent.tracefiles->len;
555
556 g_tree_destroy(tsc->pqueue);
557 tsc->pqueue = g_tree_new(compare_tracefile);
558
559 for(i = 0 ; i < nb_tracefile ; i++) {
560 tfcs =
561 LTTV_TRACEFILE_STATE(g_array_index(self->parent.tracefiles,
562 LttvTracefileContext*, i));
563 type = lttv_attribute_get(tracefiles_tree, i, &name, &value);
564 g_assert(type == LTTV_GOBJECT);
565 tracefile_tree = *((LttvAttribute **)(value.v_gobject));
566 #if 0
567 type = lttv_attribute_get_by_name(tracefile_tree, LTTV_STATE_PROCESS,
568 &value);
569 g_assert(type == LTTV_UINT);
570 pid = *(value.v_uint);
571 tfcs->process = lttv_state_find_process_or_create(tfcs, pid);
572 #endif //0
573 type = lttv_attribute_get_by_name(tracefile_tree, LTTV_STATE_EVENT,
574 &value);
575 g_assert(type == LTTV_POINTER);
576 //g_assert(*(value.v_pointer) != NULL);
577 ep = *(value.v_pointer);
578 g_assert(tfcs->parent.t_context != NULL);
579
580 LttvTracefileContext *tfc = LTTV_TRACEFILE_CONTEXT(tfcs);
581
582 if(ep != NULL) {
583 g_assert(ltt_tracefile_seek_position(tfc->tf, ep) == 0);
584 tfc->timestamp = ltt_event_time(ltt_tracefile_get_event(tfc->tf));
585 g_assert(ltt_time_compare(tfc->timestamp, ltt_time_infinite) != 0);
586 g_tree_insert(tsc->pqueue, tfc, tfc);
587 } else {
588 tfc->timestamp = ltt_time_infinite;
589 }
590 }
591 }
592
593
594 static void state_saved_free(LttvTraceState *self, LttvAttribute *container)
595 {
596 guint i, nb_tracefile, nb_cpus;
597
598 LttvTracefileState *tfcs;
599
600 LttvAttribute *tracefiles_tree, *tracefile_tree;
601
602 guint *running_process;
603
604 LttvAttributeType type;
605
606 LttvAttributeValue value;
607
608 LttvAttributeName name;
609
610 LttEventPosition *ep;
611
612 tracefiles_tree = lttv_attribute_find_subdir(container,
613 LTTV_STATE_TRACEFILES);
614 g_object_ref(G_OBJECT(tracefiles_tree));
615 lttv_attribute_remove_by_name(container, LTTV_STATE_TRACEFILES);
616
617 type = lttv_attribute_get_by_name(container, LTTV_STATE_PROCESSES,
618 &value);
619 g_assert(type == LTTV_POINTER);
620 lttv_state_free_process_table(*(value.v_pointer));
621 *(value.v_pointer) = NULL;
622 lttv_attribute_remove_by_name(container, LTTV_STATE_PROCESSES);
623
624 /* Free running processes array */
625 nb_cpus = ltt_trace_get_num_cpu(self->parent.t);
626 type = lttv_attribute_get_by_name(tracefile_tree, LTTV_STATE_RUNNING_PROCESS,
627 &value);
628 g_assert(type == LTTV_POINTER);
629 running_process = *(value.v_pointer);
630 g_free(running_process);
631
632 nb_tracefile = self->parent.tracefiles->len;
633
634 for(i = 0 ; i < nb_tracefile ; i++) {
635 tfcs =
636 LTTV_TRACEFILE_STATE(g_array_index(self->parent.tracefiles,
637 LttvTracefileContext*, i));
638 type = lttv_attribute_get(tracefiles_tree, i, &name, &value);
639 g_assert(type == LTTV_GOBJECT);
640 tracefile_tree = *((LttvAttribute **)(value.v_gobject));
641
642 type = lttv_attribute_get_by_name(tracefile_tree, LTTV_STATE_EVENT,
643 &value);
644 g_assert(type == LTTV_POINTER);
645 if(*(value.v_pointer) != NULL) g_free(*(value.v_pointer));
646 }
647 g_object_unref(G_OBJECT(tracefiles_tree));
648 }
649
650
651 static void free_saved_state(LttvTraceState *self)
652 {
653 guint i, nb;
654
655 LttvAttributeType type;
656
657 LttvAttributeValue value;
658
659 LttvAttributeName name;
660
661 LttvAttribute *saved_states;
662
663 saved_states = lttv_attribute_find_subdir(self->parent.t_a,
664 LTTV_STATE_SAVED_STATES);
665
666 nb = lttv_attribute_get_number(saved_states);
667 for(i = 0 ; i < nb ; i++) {
668 type = lttv_attribute_get(saved_states, i, &name, &value);
669 g_assert(type == LTTV_GOBJECT);
670 state_saved_free(self, *((LttvAttribute **)value.v_gobject));
671 }
672
673 lttv_attribute_remove_by_name(self->parent.t_a, LTTV_STATE_SAVED_STATES);
674 }
675
676
677 static void
678 create_max_time(LttvTraceState *tcs)
679 {
680 LttvAttributeValue v;
681
682 lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_SAVED_STATES_TIME,
683 LTTV_POINTER, &v);
684 g_assert(*(v.v_pointer) == NULL);
685 *(v.v_pointer) = g_new(LttTime,1);
686 *((LttTime *)*(v.v_pointer)) = ltt_time_zero;
687 }
688
689
690 static void
691 get_max_time(LttvTraceState *tcs)
692 {
693 LttvAttributeValue v;
694
695 lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_SAVED_STATES_TIME,
696 LTTV_POINTER, &v);
697 g_assert(*(v.v_pointer) != NULL);
698 tcs->max_time_state_recomputed_in_seek = (LttTime *)*(v.v_pointer);
699 }
700
701
702 static void
703 free_max_time(LttvTraceState *tcs)
704 {
705 LttvAttributeValue v;
706
707 lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_SAVED_STATES_TIME,
708 LTTV_POINTER, &v);
709 g_free(*(v.v_pointer));
710 *(v.v_pointer) = NULL;
711 }
712
713
714 typedef struct _LttvNameTables {
715 // FIXME GQuark *eventtype_names;
716 GQuark *syscall_names;
717 GQuark *trap_names;
718 GQuark *irq_names;
719 } LttvNameTables;
720
721
722 static void
723 create_name_tables(LttvTraceState *tcs)
724 {
725 int i, nb;
726
727 GQuark f_name, e_name;
728
729 LttvTraceHook h;
730
731 LttvTraceHookByFacility *thf;
732
733 LttEventType *et;
734
735 LttType *t;
736
737 GString *fe_name = g_string_new("");
738
739 LttvNameTables *name_tables = g_new(LttvNameTables, 1);
740
741 LttvAttributeValue v;
742
743 lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_NAME_TABLES,
744 LTTV_POINTER, &v);
745 g_assert(*(v.v_pointer) == NULL);
746 *(v.v_pointer) = name_tables;
747 #if 0 // Use iteration over the facilities_by_name and then list all event
748 // types of each facility
749 nb = ltt_trace_eventtype_number(tcs->parent.t);
750 name_tables->eventtype_names = g_new(GQuark, nb);
751 for(i = 0 ; i < nb ; i++) {
752 et = ltt_trace_eventtype_get(tcs->parent.t, i);
753 e_name = ltt_eventtype_name(et);
754 f_name = ltt_facility_name(ltt_eventtype_facility(et));
755 g_string_printf(fe_name, "%s.%s", f_name, e_name);
756 name_tables->eventtype_names[i] = g_quark_from_string(fe_name->str);
757 }
758 #endif //0
759 if(lttv_trace_find_hook(tcs->parent.t,
760 LTT_FACILITY_KERNEL, LTT_EVENT_SYSCALL_ENTRY,
761 LTT_FIELD_SYSCALL_ID, 0, 0,
762 NULL, NULL, &h))
763 return;
764
765 thf = lttv_trace_hook_get_first(&h);
766
767 t = ltt_field_type(thf->f1);
768 nb = ltt_type_element_number(t);
769
770 lttv_trace_hook_destroy(&h);
771
772 /* CHECK syscalls should be an enum but currently are not!
773 name_tables->syscall_names = g_new(GQuark, nb);
774
775 for(i = 0 ; i < nb ; i++) {
776 name_tables->syscall_names[i] = g_quark_from_string(
777 ltt_enum_string_get(t, i));
778 }
779 */
780
781 name_tables->syscall_names = g_new(GQuark, 256);
782 for(i = 0 ; i < 256 ; i++) {
783 g_string_printf(fe_name, "syscall %d", i);
784 name_tables->syscall_names[i] = g_quark_from_string(fe_name->str);
785 }
786
787 if(lttv_trace_find_hook(tcs->parent.t, LTT_FACILITY_KERNEL,
788 LTT_EVENT_TRAP_ENTRY,
789 LTT_FIELD_TRAP_ID, 0, 0,
790 NULL, NULL, &h))
791 return;
792
793 thf = lttv_trace_hook_get_first(&h);
794
795 t = ltt_field_type(thf->f1);
796 nb = ltt_type_element_number(t);
797
798 lttv_trace_hook_destroy(&h);
799
800 /*
801 name_tables->trap_names = g_new(GQuark, nb);
802 for(i = 0 ; i < nb ; i++) {
803 name_tables->trap_names[i] = g_quark_from_string(
804 ltt_enum_string_get(t, i));
805 }
806 */
807
808 name_tables->trap_names = g_new(GQuark, 256);
809 for(i = 0 ; i < 256 ; i++) {
810 g_string_printf(fe_name, "trap %d", i);
811 name_tables->trap_names[i] = g_quark_from_string(fe_name->str);
812 }
813
814 if(lttv_trace_find_hook(tcs->parent.t,
815 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
816 LTT_FIELD_IRQ_ID, 0, 0,
817 NULL, NULL, &h))
818 return;
819
820 thf = lttv_trace_hook_get_first(&h);
821
822 t = ltt_field_type(thf->f1);
823 nb = ltt_type_element_number(t);
824
825 lttv_trace_hook_destroy(&h);
826
827 /*
828 name_tables->irq_names = g_new(GQuark, nb);
829 for(i = 0 ; i < nb ; i++) {
830 name_tables->irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
831 }
832 */
833
834 name_tables->irq_names = g_new(GQuark, 256);
835 for(i = 0 ; i < 256 ; i++) {
836 g_string_printf(fe_name, "irq %d", i);
837 name_tables->irq_names[i] = g_quark_from_string(fe_name->str);
838 }
839
840 g_string_free(fe_name, TRUE);
841 }
842
843
844 static void
845 get_name_tables(LttvTraceState *tcs)
846 {
847 LttvNameTables *name_tables;
848
849 LttvAttributeValue v;
850
851 lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_NAME_TABLES,
852 LTTV_POINTER, &v);
853 g_assert(*(v.v_pointer) != NULL);
854 name_tables = (LttvNameTables *)*(v.v_pointer);
855 //tcs->eventtype_names = name_tables->eventtype_names;
856 tcs->syscall_names = name_tables->syscall_names;
857 tcs->trap_names = name_tables->trap_names;
858 tcs->irq_names = name_tables->irq_names;
859 }
860
861
862 static void
863 free_name_tables(LttvTraceState *tcs)
864 {
865 LttvNameTables *name_tables;
866
867 LttvAttributeValue v;
868
869 lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_NAME_TABLES,
870 LTTV_POINTER, &v);
871 name_tables = (LttvNameTables *)*(v.v_pointer);
872 *(v.v_pointer) = NULL;
873
874 // g_free(name_tables->eventtype_names);
875 g_free(name_tables->syscall_names);
876 g_free(name_tables->trap_names);
877 g_free(name_tables->irq_names);
878 g_free(name_tables);
879 }
880
881 static void push_state(LttvTracefileState *tfs, LttvExecutionMode t,
882 guint state_id)
883 {
884 LttvExecutionState *es;
885
886 guint cpu = ltt_tracefile_num(tfs->parent.tf);
887 LttvTraceState *ts = (LttvTraceState*)tfs->parent.t_context;
888 LttvProcessState *process = ts->running_process[cpu];
889
890 guint depth = process->execution_stack->len;
891
892 process->execution_stack =
893 g_array_set_size(process->execution_stack, depth + 1);
894 /* Keep in sync */
895 process->state =
896 &g_array_index(process->execution_stack, LttvExecutionState, depth - 1);
897
898 es = &g_array_index(process->execution_stack, LttvExecutionState, depth);
899 es->t = t;
900 es->n = state_id;
901 es->entry = es->change = tfs->parent.timestamp;
902 es->s = process->state->s;
903 process->state = es;
904 }
905
906
907 static void pop_state(LttvTracefileState *tfs, LttvExecutionMode t)
908 {
909 guint cpu = ltt_tracefile_num(tfs->parent.tf);
910 LttvTraceState *ts = (LttvTraceState*)tfs->parent.t_context;
911 LttvProcessState *process = ts->running_process[cpu];
912
913 guint depth = process->execution_stack->len;
914
915 if(process->state->t != t){
916 g_info("Different execution mode type (%lu.%09lu): ignore it\n",
917 tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec);
918 g_info("process state has %s when pop_int is %s\n",
919 g_quark_to_string(process->state->t),
920 g_quark_to_string(t));
921 g_info("{ %u, %u, %s, %s }\n",
922 process->pid,
923 process->ppid,
924 g_quark_to_string(process->name),
925 g_quark_to_string(process->state->s));
926 return;
927 }
928
929 if(depth == 1){
930 g_info("Trying to pop last state on stack (%lu.%09lu): ignore it\n",
931 tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec);
932 return;
933 }
934
935 process->execution_stack =
936 g_array_set_size(process->execution_stack, depth - 1);
937 process->state = &g_array_index(process->execution_stack, LttvExecutionState,
938 depth - 2);
939 process->state->change = tfs->parent.timestamp;
940 }
941
942
943 LttvProcessState *
944 lttv_state_create_process(LttvTraceState *tcs, LttvProcessState *parent,
945 guint cpu, guint pid, const LttTime *timestamp)
946 {
947 LttvProcessState *process = g_new(LttvProcessState, 1);
948
949 LttvExecutionState *es;
950
951 LttvTraceContext *tc = (LttvTraceContext*)tcs;
952
953 char buffer[128];
954
955 process->pid = pid;
956 process->cpu = cpu;
957 //process->last_cpu = tfs->cpu_name;
958 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
959 g_info("Process %u, core %p", process->pid, process);
960 g_hash_table_insert(tcs->processes, process, process);
961
962 if(parent) {
963 process->ppid = parent->pid;
964 process->name = parent->name;
965 process->creation_time = *timestamp;
966 }
967
968 /* No parent. This process exists but we are missing all information about
969 its creation. The birth time is set to zero but we remember the time of
970 insertion */
971
972 else {
973 process->ppid = 0;
974 process->name = LTTV_STATE_UNNAMED;
975 process->creation_time = ltt_time_zero;
976 }
977
978 process->insertion_time = *timestamp;
979 sprintf(buffer,"%d-%lu.%lu",pid, process->creation_time.tv_sec,
980 process->creation_time.tv_nsec);
981 process->pid_time = g_quark_from_string(buffer);
982 process->cpu = cpu;
983 //process->last_cpu = tfs->cpu_name;
984 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
985 process->execution_stack = g_array_sized_new(FALSE, FALSE,
986 sizeof(LttvExecutionState), PREALLOCATED_EXECUTION_STACK);
987 process->execution_stack = g_array_set_size(process->execution_stack, 1);
988 es = process->state = &g_array_index(process->execution_stack,
989 LttvExecutionState, 0);
990 es->t = LTTV_STATE_USER_MODE;
991 es->n = LTTV_STATE_SUBMODE_NONE;
992 es->entry = *timestamp;
993 //g_assert(timestamp->tv_sec != 0);
994 es->change = *timestamp;
995 es->s = LTTV_STATE_WAIT_FORK;
996
997 return process;
998 }
999
1000 LttvProcessState *lttv_state_find_process(LttvTraceState *ts, guint cpu,
1001 guint pid)
1002 {
1003 LttvProcessState key;
1004 LttvProcessState *process;
1005
1006 key.pid = pid;
1007 key.cpu = cpu;
1008 process = g_hash_table_lookup(ts->processes, &key);
1009 return process;
1010 }
1011
1012 LttvProcessState *
1013 lttv_state_find_process_or_create(LttvTraceState *ts, guint cpu, guint pid,
1014 LttTime *timestamp)
1015 {
1016 LttvProcessState *process = lttv_state_find_process(ts, cpu, pid);
1017
1018 /* Put ltt_time_zero creation time for unexisting processes */
1019 if(unlikely(process == NULL)) process = lttv_state_create_process(ts,
1020 NULL, cpu, pid, timestamp);
1021 return process;
1022 }
1023
1024 /* FIXME : this function should be called when we receive an event telling that
1025 * release_task has been called in the kernel. In happens generally when
1026 * the parent waits for its child terminaison, but may also happen in special
1027 * cases in the child's exit : when the parent ignores its children SIGCCHLD or
1028 * has the flag SA_NOCLDWAIT. It can also happen when the child is part
1029 * of a killed thread ground, but isn't the leader.
1030 */
1031 static void exit_process(LttvTracefileState *tfs, LttvProcessState *process)
1032 {
1033 LttvTraceState *ts = LTTV_TRACE_STATE(tfs->parent.t_context);
1034 LttvProcessState key;
1035
1036 key.pid = process->pid;
1037 key.cpu = process->cpu;
1038 g_hash_table_remove(ts->processes, &key);
1039 g_array_free(process->execution_stack, TRUE);
1040 g_free(process);
1041 }
1042
1043
1044 static void free_process_state(gpointer key, gpointer value,gpointer user_data)
1045 {
1046 g_array_free(((LttvProcessState *)value)->execution_stack, TRUE);
1047 g_free(value);
1048 }
1049
1050
1051 static void lttv_state_free_process_table(GHashTable *processes)
1052 {
1053 g_hash_table_foreach(processes, free_process_state, NULL);
1054 g_hash_table_destroy(processes);
1055 }
1056
1057
1058 static gboolean syscall_entry(void *hook_data, void *call_data)
1059 {
1060 LttvTracefileState *s = (LttvTracefileState *)call_data;
1061 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
1062 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
1063 LttField *f = thf->f1;
1064
1065 LttvExecutionSubmode submode;
1066
1067 submode = ((LttvTraceState *)(s->parent.t_context))->syscall_names[
1068 ltt_event_get_unsigned(e, f)];
1069 push_state(s, LTTV_STATE_SYSCALL, submode);
1070 return FALSE;
1071 }
1072
1073
1074 static gboolean syscall_exit(void *hook_data, void *call_data)
1075 {
1076 LttvTracefileState *s = (LttvTracefileState *)call_data;
1077
1078 pop_state(s, LTTV_STATE_SYSCALL);
1079 return FALSE;
1080 }
1081
1082
1083 static gboolean trap_entry(void *hook_data, void *call_data)
1084 {
1085 LttvTracefileState *s = (LttvTracefileState *)call_data;
1086 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
1087 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
1088 LttField *f = thf->f1;
1089
1090 LttvExecutionSubmode submode;
1091
1092 submode = ((LttvTraceState *)(s->parent.t_context))->trap_names[
1093 ltt_event_get_unsigned(e, f)];
1094 push_state(s, LTTV_STATE_TRAP, submode);
1095 return FALSE;
1096 }
1097
1098
1099 static gboolean trap_exit(void *hook_data, void *call_data)
1100 {
1101 LttvTracefileState *s = (LttvTracefileState *)call_data;
1102
1103 pop_state(s, LTTV_STATE_TRAP);
1104 return FALSE;
1105 }
1106
1107
1108 static gboolean irq_entry(void *hook_data, void *call_data)
1109 {
1110 LttvTracefileState *s = (LttvTracefileState *)call_data;
1111 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
1112 guint8 fac_id = ltt_event_facility_id(e);
1113 guint8 ev_id = ltt_event_eventtype_id(e);
1114 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
1115 // g_assert(lttv_trace_hook_get_first((LttvTraceHook *)hook_data)->f1 != NULL);
1116 g_assert(thf->f1 != NULL);
1117 // g_assert(thf == lttv_trace_hook_get_first((LttvTraceHook *)hook_data));
1118 LttField *f = thf->f1;
1119
1120 LttvExecutionSubmode submode;
1121
1122 submode = ((LttvTraceState *)(s->parent.t_context))->irq_names[
1123 ltt_event_get_unsigned(e, f)];
1124
1125 /* Do something with the info about being in user or system mode when int? */
1126 push_state(s, LTTV_STATE_IRQ, submode);
1127 return FALSE;
1128 }
1129
1130
1131 static gboolean irq_exit(void *hook_data, void *call_data)
1132 {
1133 LttvTracefileState *s = (LttvTracefileState *)call_data;
1134
1135 pop_state(s, LTTV_STATE_IRQ);
1136 return FALSE;
1137 }
1138
1139
1140 static gboolean schedchange(void *hook_data, void *call_data)
1141 {
1142 LttvTracefileState *s = (LttvTracefileState *)call_data;
1143 guint cpu = ltt_tracefile_num(s->parent.tf);
1144 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
1145 LttvProcessState *process = ts->running_process[cpu];
1146
1147 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
1148 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
1149 guint pid_in, pid_out;
1150 gint state_out;
1151
1152 pid_out = ltt_event_get_unsigned(e, thf->f1);
1153 pid_in = ltt_event_get_unsigned(e, thf->f2);
1154 state_out = ltt_event_get_int(e, thf->f3);
1155
1156 if(likely(process != NULL)) {
1157
1158 /* We could not know but it was not the idle process executing.
1159 This should only happen at the beginning, before the first schedule
1160 event, and when the initial information (current process for each CPU)
1161 is missing. It is not obvious how we could, after the fact, compensate
1162 the wrongly attributed statistics. */
1163
1164 //This test only makes sense once the state is known and if there is no
1165 //missing events.
1166 //if(unlikely(process->pid != pid_out)) {
1167 // g_assert(process->pid == 0);
1168 //}
1169
1170 if(unlikely(process->state->s == LTTV_STATE_EXIT)) {
1171 process->state->s = LTTV_STATE_ZOMBIE;
1172 } else {
1173 if(unlikely(state_out == 0)) process->state->s = LTTV_STATE_WAIT_CPU;
1174 else process->state->s = LTTV_STATE_WAIT;
1175 } /* FIXME : we do not remove process here, because the kernel
1176 * still has them : they may be zombies. We need to know
1177 * exactly when release_task is executed on the PID to
1178 * know when the zombie is destroyed.
1179 */
1180 //else
1181 // exit_process(s, process);
1182
1183 process->state->change = s->parent.timestamp;
1184 }
1185 process = ts->running_process[cpu] =
1186 lttv_state_find_process_or_create(
1187 (LttvTraceState*)s->parent.t_context,
1188 cpu, pid_in,
1189 &s->parent.timestamp);
1190 process->state->s = LTTV_STATE_RUN;
1191 process->cpu = cpu;
1192 // process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)s)->tf);
1193 process->state->change = s->parent.timestamp;
1194 return FALSE;
1195 }
1196
1197 static gboolean process_fork(void *hook_data, void *call_data)
1198 {
1199 LttvTracefileState *s = (LttvTracefileState *)call_data;
1200 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
1201 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
1202 LttField *f;
1203 guint parent_pid;
1204 guint child_pid;
1205 LttvProcessState *zombie_process;
1206 guint cpu = ltt_tracefile_num(s->parent.tf);
1207 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
1208 LttvProcessState *process = ts->running_process[cpu];
1209
1210 /* Parent PID */
1211 f = thf->f1;
1212 parent_pid = ltt_event_get_unsigned(e, f);
1213
1214 /* Child PID */
1215 f = thf->f2;
1216 child_pid = ltt_event_get_unsigned(e, f);
1217
1218 zombie_process = lttv_state_find_process(ts, ANY_CPU, child_pid);
1219
1220 if(unlikely(zombie_process != NULL)) {
1221 /* Reutilisation of PID. Only now we are sure that the old PID
1222 * has been released. FIXME : should know when release_task happens instead.
1223 */
1224 exit_process(s, zombie_process);
1225 }
1226 g_assert(process->pid != child_pid);
1227 // FIXME : Add this test in the "known state" section
1228 // g_assert(process->pid == parent_pid);
1229 lttv_state_create_process(ts, process, cpu, child_pid, &s->parent.timestamp);
1230
1231 return FALSE;
1232 }
1233
1234
1235 static gboolean process_exit(void *hook_data, void *call_data)
1236 {
1237 LttvTracefileState *s = (LttvTracefileState *)call_data;
1238 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
1239 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
1240 LttField *f;
1241 guint pid;
1242 guint cpu = ltt_tracefile_num(s->parent.tf);
1243 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
1244 LttvProcessState *process = ts->running_process[cpu];
1245
1246 pid = ltt_event_get_unsigned(e, thf->f1);
1247
1248 // FIXME : Add this test in the "known state" section
1249 // g_assert(process->pid == pid);
1250
1251 if(likely(process != NULL)) {
1252 process->state->s = LTTV_STATE_EXIT;
1253 }
1254 return FALSE;
1255 }
1256
1257 static gboolean process_free(void *hook_data, void *call_data)
1258 {
1259 LttvTracefileState *s = (LttvTracefileState *)call_data;
1260 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
1261 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
1262 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
1263 guint release_pid;
1264 LttvProcessState *process;
1265
1266 /* PID of the process to release */
1267 release_pid = ltt_event_get_unsigned(e, thf->f1);
1268
1269 process = lttv_state_find_process(ts, ANY_CPU, release_pid);
1270
1271 if(likely(process != NULL)) {
1272 /* release_task is happening at kernel level : we can now safely release
1273 * the data structure of the process */
1274 exit_process(s, process);
1275 }
1276
1277 return FALSE;
1278 }
1279
1280 gint lttv_state_hook_add_event_hooks(void *hook_data, void *call_data)
1281 {
1282 LttvTracesetState *tss = (LttvTracesetState*)(call_data);
1283
1284 lttv_state_add_event_hooks(tss);
1285
1286 return 0;
1287 }
1288
1289 void lttv_state_add_event_hooks(LttvTracesetState *self)
1290 {
1291 LttvTraceset *traceset = self->parent.ts;
1292
1293 guint i, j, k, l, nb_trace, nb_tracefile;
1294
1295 LttvTraceState *ts;
1296
1297 LttvTracefileState *tfs;
1298
1299 GArray *hooks;
1300
1301 LttvTraceHookByFacility *thf;
1302
1303 LttvTraceHook *hook;
1304
1305 LttvAttributeValue val;
1306
1307 gint ret;
1308
1309 nb_trace = lttv_traceset_number(traceset);
1310 for(i = 0 ; i < nb_trace ; i++) {
1311 ts = (LttvTraceState *)self->parent.traces[i];
1312
1313 /* Find the eventtype id for the following events and register the
1314 associated by id hooks. */
1315
1316 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 10);
1317 hooks = g_array_set_size(hooks, 10);
1318
1319 ret = lttv_trace_find_hook(ts->parent.t,
1320 LTT_FACILITY_KERNEL, LTT_EVENT_SYSCALL_ENTRY,
1321 LTT_FIELD_SYSCALL_ID, 0, 0,
1322 syscall_entry, NULL, &g_array_index(hooks, LttvTraceHook, 0));
1323 g_assert(!ret);
1324
1325 ret = lttv_trace_find_hook(ts->parent.t,
1326 LTT_FACILITY_KERNEL, LTT_EVENT_SYSCALL_EXIT,
1327 0, 0, 0,
1328 syscall_exit, NULL, &g_array_index(hooks, LttvTraceHook, 1));
1329 g_assert(!ret);
1330
1331 ret = lttv_trace_find_hook(ts->parent.t,
1332 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY,
1333 LTT_FIELD_TRAP_ID, 0, 0,
1334 trap_entry, NULL, &g_array_index(hooks, LttvTraceHook, 2));
1335 g_assert(!ret);
1336
1337 ret = lttv_trace_find_hook(ts->parent.t,
1338 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT,
1339 0, 0, 0,
1340 trap_exit, NULL, &g_array_index(hooks, LttvTraceHook, 3));
1341 g_assert(!ret);
1342
1343 ret = lttv_trace_find_hook(ts->parent.t,
1344 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
1345 LTT_FIELD_IRQ_ID, 0, 0,
1346 irq_entry, NULL, &g_array_index(hooks, LttvTraceHook, 4));
1347 g_assert(!ret);
1348
1349 ret = lttv_trace_find_hook(ts->parent.t,
1350 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
1351 0, 0, 0,
1352 irq_exit, NULL, &g_array_index(hooks, LttvTraceHook, 5));
1353 g_assert(!ret);
1354
1355 ret = lttv_trace_find_hook(ts->parent.t,
1356 LTT_FACILITY_PROCESS, LTT_EVENT_SCHEDCHANGE,
1357 LTT_FIELD_OUT, LTT_FIELD_IN, LTT_FIELD_OUT_STATE,
1358 schedchange, NULL, &g_array_index(hooks, LttvTraceHook, 6));
1359 g_assert(!ret);
1360
1361 ret = lttv_trace_find_hook(ts->parent.t,
1362 LTT_FACILITY_PROCESS, LTT_EVENT_FORK,
1363 LTT_FIELD_PARENT_PID, LTT_FIELD_CHILD_PID, 0,
1364 process_fork, NULL, &g_array_index(hooks, LttvTraceHook, 7));
1365 g_assert(!ret);
1366
1367 ret = lttv_trace_find_hook(ts->parent.t,
1368 LTT_FACILITY_PROCESS, LTT_EVENT_EXIT,
1369 LTT_FIELD_PID, 0, 0,
1370 process_exit, NULL, &g_array_index(hooks, LttvTraceHook, 8));
1371 g_assert(!ret);
1372
1373 ret = lttv_trace_find_hook(ts->parent.t,
1374 LTT_FACILITY_PROCESS, LTT_EVENT_FREE,
1375 LTT_FIELD_PID, 0, 0,
1376 process_free, NULL, &g_array_index(hooks, LttvTraceHook, 9));
1377 g_assert(!ret);
1378
1379
1380 /* Add these hooks to each event_by_id hooks list */
1381
1382 nb_tracefile = ts->parent.tracefiles->len;
1383
1384 for(j = 0 ; j < nb_tracefile ; j++) {
1385 tfs =
1386 LTTV_TRACEFILE_STATE(g_array_index(ts->parent.tracefiles,
1387 LttvTracefileContext*, j));
1388
1389 for(k = 0 ; k < hooks->len ; k++) {
1390 hook = &g_array_index(hooks, LttvTraceHook, k);
1391 for(l=0;l<hook->fac_list->len;l++) {
1392 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1393 lttv_hooks_add(
1394 lttv_hooks_by_id_find(tfs->parent.event_by_id, thf->id),
1395 thf->h,
1396 thf,
1397 LTTV_PRIO_STATE);
1398 }
1399 }
1400 }
1401 lttv_attribute_find(self->parent.a, LTTV_STATE_HOOKS, LTTV_POINTER, &val);
1402 *(val.v_pointer) = hooks;
1403 }
1404 }
1405
1406 gint lttv_state_hook_remove_event_hooks(void *hook_data, void *call_data)
1407 {
1408 LttvTracesetState *tss = (LttvTracesetState*)(call_data);
1409
1410 lttv_state_remove_event_hooks(tss);
1411
1412 return 0;
1413 }
1414
1415 void lttv_state_remove_event_hooks(LttvTracesetState *self)
1416 {
1417 LttvTraceset *traceset = self->parent.ts;
1418
1419 guint i, j, k, l, nb_trace, nb_tracefile;
1420
1421 LttvTraceState *ts;
1422
1423 LttvTracefileState *tfs;
1424
1425 GArray *hooks;
1426
1427 LttvTraceHook *hook;
1428
1429 LttvTraceHookByFacility *thf;
1430
1431 LttvAttributeValue val;
1432
1433 nb_trace = lttv_traceset_number(traceset);
1434 for(i = 0 ; i < nb_trace ; i++) {
1435 ts = LTTV_TRACE_STATE(self->parent.traces[i]);
1436 lttv_attribute_find(self->parent.a, LTTV_STATE_HOOKS, LTTV_POINTER, &val);
1437 hooks = *(val.v_pointer);
1438
1439 /* Remove these hooks from each event_by_id hooks list */
1440
1441 nb_tracefile = ts->parent.tracefiles->len;
1442
1443 for(j = 0 ; j < nb_tracefile ; j++) {
1444 tfs =
1445 LTTV_TRACEFILE_STATE(g_array_index(ts->parent.tracefiles,
1446 LttvTracefileContext*, j));
1447
1448 for(k = 0 ; k < hooks->len ; k++) {
1449 hook = &g_array_index(hooks, LttvTraceHook, k);
1450 for(l=0;l<hook->fac_list->len;l++) {
1451 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1452
1453 lttv_hooks_remove_data(
1454 lttv_hooks_by_id_find(tfs->parent.event_by_id, thf->id),
1455 thf->h,
1456 thf);
1457 }
1458 }
1459 }
1460 for(k = 0 ; k < hooks->len ; k++)
1461 lttv_trace_hook_destroy(&g_array_index(hooks, LttvTraceHook, k));
1462 g_array_free(hooks, TRUE);
1463 }
1464 }
1465
1466 static guint test_event_count = 0;
1467 static gboolean state_save_event_hook(void *hook_data, void *call_data)
1468 {
1469 guint *event_count = (guint*)hook_data;
1470
1471 test_event_count++;
1472 /* Only save at LTTV_STATE_SAVE_INTERVAL */
1473 if(likely((*event_count)++ < LTTV_STATE_SAVE_INTERVAL))
1474 return FALSE;
1475 else
1476 *event_count = 0;
1477
1478 LttvTracefileState *self = (LttvTracefileState *)call_data;
1479
1480 LttvTracefileState *tfcs;
1481
1482 LttvTraceState *tcs = (LttvTraceState *)(self->parent.t_context);
1483
1484 LttEventPosition *ep;
1485
1486 guint i;
1487
1488 LttTracefile *tf;
1489
1490 LttvAttribute *saved_states_tree, *saved_state_tree;
1491
1492 LttvAttributeValue value;
1493
1494 saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a,
1495 LTTV_STATE_SAVED_STATES);
1496 saved_state_tree = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
1497 value = lttv_attribute_add(saved_states_tree,
1498 lttv_attribute_get_number(saved_states_tree), LTTV_GOBJECT);
1499 *(value.v_gobject) = (GObject *)saved_state_tree;
1500 value = lttv_attribute_add(saved_state_tree, LTTV_STATE_TIME, LTTV_TIME);
1501 *(value.v_time) = self->parent.timestamp;
1502 lttv_state_save(tcs, saved_state_tree);
1503 g_debug("Saving state at time %lu.%lu", self->parent.timestamp.tv_sec,
1504 self->parent.timestamp.tv_nsec);
1505
1506 *(tcs->max_time_state_recomputed_in_seek) = self->parent.timestamp;
1507
1508 return FALSE;
1509 }
1510
1511 #if 0
1512 static gboolean block_start(void *hook_data, void *call_data)
1513 {
1514 LttvTracefileState *self = (LttvTracefileState *)call_data;
1515
1516 LttvTracefileState *tfcs;
1517
1518 LttvTraceState *tcs = (LttvTraceState *)(self->parent.t_context);
1519
1520 LttEventPosition *ep;
1521
1522 guint i, nb_block, nb_event, nb_tracefile;
1523
1524 LttTracefile *tf;
1525
1526 LttvAttribute *saved_states_tree, *saved_state_tree;
1527
1528 LttvAttributeValue value;
1529
1530 ep = ltt_event_position_new();
1531
1532 nb_tracefile = tcs->parent.tracefiles->len;
1533
1534 /* Count the number of events added since the last block end in any
1535 tracefile. */
1536
1537 for(i = 0 ; i < nb_tracefile ; i++) {
1538 tfcs =
1539 LTTV_TRACEFILE_STATE(&g_array_index(tcs->parent.tracefiles,
1540 LttvTracefileContext, i));
1541 ltt_event_position(tfcs->parent.e, ep);
1542 ltt_event_position_get(ep, &nb_block, &nb_event, &tf);
1543 tcs->nb_event += nb_event - tfcs->saved_position;
1544 tfcs->saved_position = nb_event;
1545 }
1546 g_free(ep);
1547
1548 if(tcs->nb_event >= tcs->save_interval) {
1549 saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a,
1550 LTTV_STATE_SAVED_STATES);
1551 saved_state_tree = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
1552 value = lttv_attribute_add(saved_states_tree,
1553 lttv_attribute_get_number(saved_states_tree), LTTV_GOBJECT);
1554 *(value.v_gobject) = (GObject *)saved_state_tree;
1555 value = lttv_attribute_add(saved_state_tree, LTTV_STATE_TIME, LTTV_TIME);
1556 *(value.v_time) = self->parent.timestamp;
1557 lttv_state_save(tcs, saved_state_tree);
1558 tcs->nb_event = 0;
1559 g_debug("Saving state at time %lu.%lu", self->parent.timestamp.tv_sec,
1560 self->parent.timestamp.tv_nsec);
1561 }
1562 *(tcs->max_time_state_recomputed_in_seek) = self->parent.timestamp;
1563 return FALSE;
1564 }
1565 #endif //0
1566
1567 #if 0
1568 static gboolean block_end(void *hook_data, void *call_data)
1569 {
1570 LttvTracefileState *self = (LttvTracefileState *)call_data;
1571
1572 LttvTraceState *tcs = (LttvTraceState *)(self->parent.t_context);
1573
1574 LttTracefile *tf;
1575
1576 LttEventPosition *ep;
1577
1578 guint nb_block, nb_event;
1579
1580 ep = ltt_event_position_new();
1581 ltt_event_position(self->parent.e, ep);
1582 ltt_event_position_get(ep, &nb_block, &nb_event, &tf);
1583 tcs->nb_event += nb_event - self->saved_position + 1;
1584 self->saved_position = 0;
1585 *(tcs->max_time_state_recomputed_in_seek) = self->parent.timestamp;
1586 g_free(ep);
1587
1588 return FALSE;
1589 }
1590 #endif //0
1591 #if 0
1592 void lttv_state_save_add_event_hooks(LttvTracesetState *self)
1593 {
1594 LttvTraceset *traceset = self->parent.ts;
1595
1596 guint i, j, nb_trace, nb_tracefile;
1597
1598 LttvTraceState *ts;
1599
1600 LttvTracefileState *tfs;
1601
1602 LttvTraceHook hook_start, hook_end;
1603
1604 nb_trace = lttv_traceset_number(traceset);
1605 for(i = 0 ; i < nb_trace ; i++) {
1606 ts = (LttvTraceState *)self->parent.traces[i];
1607
1608 lttv_trace_find_hook(ts->parent.t, "core","block_start",NULL,
1609 NULL, NULL, block_start, &hook_start);
1610 lttv_trace_find_hook(ts->parent.t, "core","block_end",NULL,
1611 NULL, NULL, block_end, &hook_end);
1612
1613 nb_tracefile = ts->parent.tracefiles->len;
1614
1615 for(j = 0 ; j < nb_tracefile ; j++) {
1616 tfs =
1617 LTTV_TRACEFILE_STATE(&g_array_index(ts->parent.tracefiles,
1618 LttvTracefileContext, j));
1619 lttv_hooks_add(lttv_hooks_by_id_find(tfs->parent.event_by_id,
1620 hook_start.id), hook_start.h, NULL, LTTV_PRIO_STATE);
1621 lttv_hooks_add(lttv_hooks_by_id_find(tfs->parent.event_by_id,
1622 hook_end.id), hook_end.h, NULL, LTTV_PRIO_STATE);
1623 }
1624 }
1625 }
1626 #endif //0
1627
1628 void lttv_state_save_add_event_hooks(LttvTracesetState *self)
1629 {
1630 LttvTraceset *traceset = self->parent.ts;
1631
1632 guint i, j, nb_trace, nb_tracefile;
1633
1634 LttvTraceState *ts;
1635
1636 LttvTracefileState *tfs;
1637
1638
1639 nb_trace = lttv_traceset_number(traceset);
1640 for(i = 0 ; i < nb_trace ; i++) {
1641
1642 ts = (LttvTraceState *)self->parent.traces[i];
1643 nb_tracefile = ts->parent.tracefiles->len;
1644
1645 guint *event_count = g_new(guint, 1);
1646 *event_count = 0;
1647
1648 for(j = 0 ; j < nb_tracefile ; j++) {
1649 tfs =
1650 LTTV_TRACEFILE_STATE(g_array_index(ts->parent.tracefiles,
1651 LttvTracefileContext*, j));
1652 lttv_hooks_add(tfs->parent.event,
1653 state_save_event_hook,
1654 event_count,
1655 LTTV_PRIO_STATE);
1656
1657 }
1658 }
1659 }
1660
1661 gint lttv_state_save_hook_add_event_hooks(void *hook_data, void *call_data)
1662 {
1663 LttvTracesetState *tss = (LttvTracesetState*)(call_data);
1664
1665 lttv_state_save_add_event_hooks(tss);
1666
1667 return 0;
1668 }
1669
1670
1671 #if 0
1672 void lttv_state_save_remove_event_hooks(LttvTracesetState *self)
1673 {
1674 LttvTraceset *traceset = self->parent.ts;
1675
1676 guint i, j, nb_trace, nb_tracefile;
1677
1678 LttvTraceState *ts;
1679
1680 LttvTracefileState *tfs;
1681
1682 LttvTraceHook hook_start, hook_end;
1683
1684 nb_trace = lttv_traceset_number(traceset);
1685 for(i = 0 ; i < nb_trace ; i++) {
1686 ts = LTTV_TRACE_STATE(self->parent.traces[i]);
1687
1688 lttv_trace_find_hook(ts->parent.t, "core","block_start",NULL,
1689 NULL, NULL, block_start, &hook_start);
1690
1691 lttv_trace_find_hook(ts->parent.t, "core","block_end",NULL,
1692 NULL, NULL, block_end, &hook_end);
1693
1694 nb_tracefile = ts->parent.tracefiles->len;
1695
1696 for(j = 0 ; j < nb_tracefile ; j++) {
1697 tfs =
1698 LTTV_TRACEFILE_STATE(&g_array_index(ts->parent.tracefiles,
1699 LttvTracefileContext, j));
1700 lttv_hooks_remove_data(lttv_hooks_by_id_find(
1701 tfs->parent.event_by_id, hook_start.id), hook_start.h, NULL);
1702 lttv_hooks_remove_data(lttv_hooks_by_id_find(
1703 tfs->parent.event_by_id, hook_end.id), hook_end.h, NULL);
1704 }
1705 }
1706 }
1707 #endif //0
1708
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
1720 nb_trace = lttv_traceset_number(traceset);
1721 for(i = 0 ; i < nb_trace ; i++) {
1722
1723 ts = (LttvTraceState *)self->parent.traces[i];
1724 nb_tracefile = ts->parent.tracefiles->len;
1725
1726 guint *event_count;
1727
1728 for(j = 0 ; j < nb_tracefile ; j++) {
1729 tfs =
1730 LTTV_TRACEFILE_STATE(g_array_index(ts->parent.tracefiles,
1731 LttvTracefileContext*, j));
1732 event_count = lttv_hooks_remove(tfs->parent.event,
1733 state_save_event_hook);
1734
1735 }
1736 g_free(event_count);
1737 }
1738 g_info("EVENT COUNT TEST : %u", test_event_count);
1739 }
1740
1741 gint lttv_state_save_hook_remove_event_hooks(void *hook_data, void *call_data)
1742 {
1743 LttvTracesetState *tss = (LttvTracesetState*)(call_data);
1744
1745 lttv_state_save_remove_event_hooks(tss);
1746
1747 return 0;
1748 }
1749
1750 void lttv_state_traceset_seek_time_closest(LttvTracesetState *self, LttTime t)
1751 {
1752 LttvTraceset *traceset = self->parent.ts;
1753
1754 guint i, nb_trace;
1755
1756 int min_pos, mid_pos, max_pos;
1757
1758 LttvTraceState *tcs;
1759
1760 LttvAttributeValue value;
1761
1762 LttvAttributeType type;
1763
1764 LttvAttributeName name;
1765
1766 LttvAttribute *saved_states_tree, *saved_state_tree, *closest_tree;
1767
1768 g_tree_destroy(self->parent.pqueue);
1769 self->parent.pqueue = g_tree_new(compare_tracefile);
1770
1771 nb_trace = lttv_traceset_number(traceset);
1772 for(i = 0 ; i < nb_trace ; i++) {
1773 tcs = (LttvTraceState *)self->parent.traces[i];
1774
1775 if(ltt_time_compare(t, *(tcs->max_time_state_recomputed_in_seek)) < 0) {
1776 saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a,
1777 LTTV_STATE_SAVED_STATES);
1778 min_pos = -1;
1779
1780 if(saved_states_tree) {
1781 max_pos = lttv_attribute_get_number(saved_states_tree) - 1;
1782 mid_pos = max_pos / 2;
1783 while(min_pos < max_pos) {
1784 type = lttv_attribute_get(saved_states_tree, mid_pos, &name, &value);
1785 g_assert(type == LTTV_GOBJECT);
1786 saved_state_tree = *((LttvAttribute **)(value.v_gobject));
1787 type = lttv_attribute_get_by_name(saved_state_tree, LTTV_STATE_TIME,
1788 &value);
1789 g_assert(type == LTTV_TIME);
1790 if(ltt_time_compare(*(value.v_time), t) < 0) {
1791 min_pos = mid_pos;
1792 closest_tree = saved_state_tree;
1793 }
1794 else max_pos = mid_pos - 1;
1795
1796 mid_pos = (min_pos + max_pos + 1) / 2;
1797 }
1798 }
1799
1800 /* restore the closest earlier saved state */
1801 if(min_pos != -1) {
1802 lttv_state_restore(tcs, closest_tree);
1803 }
1804
1805 /* There is no saved state, yet we want to have it. Restart at T0 */
1806 else {
1807 restore_init_state(tcs);
1808 lttv_process_trace_seek_time(&(tcs->parent), ltt_time_zero);
1809 }
1810 }
1811 /* We want to seek quickly without restoring/updating the state */
1812 else {
1813 restore_init_state(tcs);
1814 lttv_process_trace_seek_time(&(tcs->parent), t);
1815 }
1816 }
1817 }
1818
1819
1820 static void
1821 traceset_state_instance_init (GTypeInstance *instance, gpointer g_class)
1822 {
1823 }
1824
1825
1826 static void
1827 traceset_state_finalize (LttvTracesetState *self)
1828 {
1829 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))->
1830 finalize(G_OBJECT(self));
1831 }
1832
1833
1834 static void
1835 traceset_state_class_init (LttvTracesetContextClass *klass)
1836 {
1837 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
1838
1839 gobject_class->finalize = (void (*)(GObject *self)) traceset_state_finalize;
1840 klass->init = (void (*)(LttvTracesetContext *self, LttvTraceset *ts))init;
1841 klass->fini = (void (*)(LttvTracesetContext *self))fini;
1842 klass->new_traceset_context = new_traceset_context;
1843 klass->new_trace_context = new_trace_context;
1844 klass->new_tracefile_context = new_tracefile_context;
1845 }
1846
1847
1848 GType
1849 lttv_traceset_state_get_type(void)
1850 {
1851 static GType type = 0;
1852 if (type == 0) {
1853 static const GTypeInfo info = {
1854 sizeof (LttvTracesetStateClass),
1855 NULL, /* base_init */
1856 NULL, /* base_finalize */
1857 (GClassInitFunc) traceset_state_class_init, /* class_init */
1858 NULL, /* class_finalize */
1859 NULL, /* class_data */
1860 sizeof (LttvTracesetState),
1861 0, /* n_preallocs */
1862 (GInstanceInitFunc) traceset_state_instance_init, /* instance_init */
1863 NULL /* value handling */
1864 };
1865
1866 type = g_type_register_static (LTTV_TRACESET_CONTEXT_TYPE, "LttvTracesetStateType",
1867 &info, 0);
1868 }
1869 return type;
1870 }
1871
1872
1873 static void
1874 trace_state_instance_init (GTypeInstance *instance, gpointer g_class)
1875 {
1876 }
1877
1878
1879 static void
1880 trace_state_finalize (LttvTraceState *self)
1881 {
1882 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_CONTEXT_TYPE))->
1883 finalize(G_OBJECT(self));
1884 }
1885
1886
1887 static void
1888 trace_state_class_init (LttvTraceStateClass *klass)
1889 {
1890 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
1891
1892 gobject_class->finalize = (void (*)(GObject *self)) trace_state_finalize;
1893 klass->state_save = state_save;
1894 klass->state_restore = state_restore;
1895 klass->state_saved_free = state_saved_free;
1896 }
1897
1898
1899 GType
1900 lttv_trace_state_get_type(void)
1901 {
1902 static GType type = 0;
1903 if (type == 0) {
1904 static const GTypeInfo info = {
1905 sizeof (LttvTraceStateClass),
1906 NULL, /* base_init */
1907 NULL, /* base_finalize */
1908 (GClassInitFunc) trace_state_class_init, /* class_init */
1909 NULL, /* class_finalize */
1910 NULL, /* class_data */
1911 sizeof (LttvTraceState),
1912 0, /* n_preallocs */
1913 (GInstanceInitFunc) trace_state_instance_init, /* instance_init */
1914 NULL /* value handling */
1915 };
1916
1917 type = g_type_register_static (LTTV_TRACE_CONTEXT_TYPE,
1918 "LttvTraceStateType", &info, 0);
1919 }
1920 return type;
1921 }
1922
1923
1924 static void
1925 tracefile_state_instance_init (GTypeInstance *instance, gpointer g_class)
1926 {
1927 }
1928
1929
1930 static void
1931 tracefile_state_finalize (LttvTracefileState *self)
1932 {
1933 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_CONTEXT_TYPE))->
1934 finalize(G_OBJECT(self));
1935 }
1936
1937
1938 static void
1939 tracefile_state_class_init (LttvTracefileStateClass *klass)
1940 {
1941 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
1942
1943 gobject_class->finalize = (void (*)(GObject *self)) tracefile_state_finalize;
1944 }
1945
1946
1947 GType
1948 lttv_tracefile_state_get_type(void)
1949 {
1950 static GType type = 0;
1951 if (type == 0) {
1952 static const GTypeInfo info = {
1953 sizeof (LttvTracefileStateClass),
1954 NULL, /* base_init */
1955 NULL, /* base_finalize */
1956 (GClassInitFunc) tracefile_state_class_init, /* class_init */
1957 NULL, /* class_finalize */
1958 NULL, /* class_data */
1959 sizeof (LttvTracefileState),
1960 0, /* n_preallocs */
1961 (GInstanceInitFunc) tracefile_state_instance_init, /* instance_init */
1962 NULL /* value handling */
1963 };
1964
1965 type = g_type_register_static (LTTV_TRACEFILE_CONTEXT_TYPE,
1966 "LttvTracefileStateType", &info, 0);
1967 }
1968 return type;
1969 }
1970
1971
1972 static void module_init()
1973 {
1974 LTTV_STATE_UNNAMED = g_quark_from_string("unnamed");
1975 LTTV_STATE_MODE_UNKNOWN = g_quark_from_string("unknown execution mode");
1976 LTTV_STATE_USER_MODE = g_quark_from_string("user mode");
1977 LTTV_STATE_WAIT_FORK = g_quark_from_string("wait fork");
1978 LTTV_STATE_SYSCALL = g_quark_from_string("system call");
1979 LTTV_STATE_TRAP = g_quark_from_string("trap");
1980 LTTV_STATE_IRQ = g_quark_from_string("irq");
1981 LTTV_STATE_SUBMODE_UNKNOWN = g_quark_from_string("unknown submode");
1982 LTTV_STATE_SUBMODE_NONE = g_quark_from_string("(no submode)");
1983 LTTV_STATE_WAIT_CPU = g_quark_from_string("wait for cpu");
1984 LTTV_STATE_EXIT = g_quark_from_string("exiting");
1985 LTTV_STATE_ZOMBIE = g_quark_from_string("zombie");
1986 LTTV_STATE_WAIT = g_quark_from_string("wait for I/O");
1987 LTTV_STATE_RUN = g_quark_from_string("running");
1988 LTTV_STATE_TRACEFILES = g_quark_from_string("tracefiles");
1989 LTTV_STATE_PROCESSES = g_quark_from_string("processes");
1990 LTTV_STATE_PROCESS = g_quark_from_string("process");
1991 LTTV_STATE_RUNNING_PROCESS = g_quark_from_string("running_process");
1992 LTTV_STATE_EVENT = g_quark_from_string("event");
1993 LTTV_STATE_SAVED_STATES = g_quark_from_string("saved states");
1994 LTTV_STATE_SAVED_STATES_TIME = g_quark_from_string("saved states time");
1995 LTTV_STATE_TIME = g_quark_from_string("time");
1996 LTTV_STATE_HOOKS = g_quark_from_string("saved state hooks");
1997 LTTV_STATE_NAME_TABLES = g_quark_from_string("name tables");
1998 LTTV_STATE_TRACE_STATE_USE_COUNT =
1999 g_quark_from_string("trace_state_use_count");
2000
2001
2002 LTT_FACILITY_KERNEL = g_quark_from_string("kernel");
2003 LTT_FACILITY_PROCESS = g_quark_from_string("process");
2004
2005
2006 LTT_EVENT_SYSCALL_ENTRY = g_quark_from_string("syscall_entry");
2007 LTT_EVENT_SYSCALL_EXIT = g_quark_from_string("syscall_exit");
2008 LTT_EVENT_TRAP_ENTRY = g_quark_from_string("trap_entry");
2009 LTT_EVENT_TRAP_EXIT = g_quark_from_string("trap_exit");
2010 LTT_EVENT_IRQ_ENTRY = g_quark_from_string("irq_entry");
2011 LTT_EVENT_IRQ_EXIT = g_quark_from_string("irq_exit");
2012 LTT_EVENT_SCHEDCHANGE = g_quark_from_string("schedchange");
2013 LTT_EVENT_FORK = g_quark_from_string("fork");
2014 LTT_EVENT_EXIT = g_quark_from_string("exit");
2015 LTT_EVENT_FREE = g_quark_from_string("free");
2016
2017
2018 LTT_FIELD_SYSCALL_ID = g_quark_from_string("syscall_id");
2019 LTT_FIELD_TRAP_ID = g_quark_from_string("trap_id");
2020 LTT_FIELD_IRQ_ID = g_quark_from_string("irq_id");
2021 LTT_FIELD_OUT = g_quark_from_string("out");
2022 LTT_FIELD_IN = g_quark_from_string("in");
2023 LTT_FIELD_OUT_STATE = g_quark_from_string("out_state");
2024 LTT_FIELD_PARENT_PID = g_quark_from_string("parent_pid");
2025 LTT_FIELD_CHILD_PID = g_quark_from_string("child_pid");
2026 LTT_FIELD_PID = g_quark_from_string("pid");
2027
2028 }
2029
2030 static void module_destroy()
2031 {
2032 }
2033
2034
2035 LTTV_MODULE("state", "State computation", \
2036 "Update the system state, possibly saving it at intervals", \
2037 module_init, module_destroy)
2038
2039
2040
This page took 0.114322 seconds and 5 git commands to generate.