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