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