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