change find_field
[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);
b445142a 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);
b445142a 807 nb = ltt_type_element_number(t);
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);
b445142a 834 nb = ltt_type_element_number(t);
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;
1378 gchar *name;
1379 guint cpu = ltt_tracefile_num(s->parent.tf);
1380 LttvProcessState *process = ts->running_process[cpu];
1381
1382 /* PID of the process to release */
1383 name = ltt_event_get_string(e, thf->f1);
1384
1385 process->name = g_quark_from_string(name);
1386
1387 return FALSE;
1388}
1389
1390
1391
1392
58c88a41 1393gint lttv_state_hook_add_event_hooks(void *hook_data, void *call_data)
1394{
1395 LttvTracesetState *tss = (LttvTracesetState*)(call_data);
1396
1397 lttv_state_add_event_hooks(tss);
1398
1399 return 0;
1400}
dc877563 1401
308711e5 1402void lttv_state_add_event_hooks(LttvTracesetState *self)
dc877563 1403{
ba576a78 1404 LttvTraceset *traceset = self->parent.ts;
dc877563 1405
eed2ef37 1406 guint i, j, k, l, nb_trace, nb_tracefile;
dc877563 1407
ba576a78 1408 LttvTraceState *ts;
dc877563 1409
ba576a78 1410 LttvTracefileState *tfs;
dc877563 1411
dc877563 1412 GArray *hooks;
1413
eed2ef37 1414 LttvTraceHookByFacility *thf;
1415
1416 LttvTraceHook *hook;
dc877563 1417
1418 LttvAttributeValue val;
1419
9d239bd9 1420 gint ret;
1421
ba576a78 1422 nb_trace = lttv_traceset_number(traceset);
dc877563 1423 for(i = 0 ; i < nb_trace ; i++) {
ba576a78 1424 ts = (LttvTraceState *)self->parent.traces[i];
dc877563 1425
1426 /* Find the eventtype id for the following events and register the
1427 associated by id hooks. */
1428
f4b88a7d 1429 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 11);
1430 hooks = g_array_set_size(hooks, 11);
b445142a 1431
9d239bd9 1432 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 1433 LTT_FACILITY_KERNEL, LTT_EVENT_SYSCALL_ENTRY,
1434 LTT_FIELD_SYSCALL_ID, 0, 0,
2c82c4dc 1435 syscall_entry, NULL, &g_array_index(hooks, LttvTraceHook, 0));
9d239bd9 1436 g_assert(!ret);
cbe7c836 1437
9d239bd9 1438 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 1439 LTT_FACILITY_KERNEL, LTT_EVENT_SYSCALL_EXIT,
1440 0, 0, 0,
2c82c4dc 1441 syscall_exit, NULL, &g_array_index(hooks, LttvTraceHook, 1));
9d239bd9 1442 g_assert(!ret);
cbe7c836 1443
9d239bd9 1444 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 1445 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY,
1446 LTT_FIELD_TRAP_ID, 0, 0,
2c82c4dc 1447 trap_entry, NULL, &g_array_index(hooks, LttvTraceHook, 2));
9d239bd9 1448 g_assert(!ret);
cbe7c836 1449
9d239bd9 1450 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 1451 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT,
1452 0, 0, 0,
2c82c4dc 1453 trap_exit, NULL, &g_array_index(hooks, LttvTraceHook, 3));
9d239bd9 1454 g_assert(!ret);
cbe7c836 1455
9d239bd9 1456 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 1457 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
1458 LTT_FIELD_IRQ_ID, 0, 0,
2c82c4dc 1459 irq_entry, NULL, &g_array_index(hooks, LttvTraceHook, 4));
9d239bd9 1460 g_assert(!ret);
cbe7c836 1461
9d239bd9 1462 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 1463 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
1464 0, 0, 0,
2c82c4dc 1465 irq_exit, NULL, &g_array_index(hooks, LttvTraceHook, 5));
9d239bd9 1466 g_assert(!ret);
cbe7c836 1467
9d239bd9 1468 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 1469 LTT_FACILITY_PROCESS, LTT_EVENT_SCHEDCHANGE,
1470 LTT_FIELD_OUT, LTT_FIELD_IN, LTT_FIELD_OUT_STATE,
2c82c4dc 1471 schedchange, NULL, &g_array_index(hooks, LttvTraceHook, 6));
9d239bd9 1472 g_assert(!ret);
cbe7c836 1473
9d239bd9 1474 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 1475 LTT_FACILITY_PROCESS, LTT_EVENT_FORK,
1476 LTT_FIELD_PARENT_PID, LTT_FIELD_CHILD_PID, 0,
2c82c4dc 1477 process_fork, NULL, &g_array_index(hooks, LttvTraceHook, 7));
9d239bd9 1478 g_assert(!ret);
eed2ef37 1479
9d239bd9 1480 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 1481 LTT_FACILITY_PROCESS, LTT_EVENT_EXIT,
1482 LTT_FIELD_PID, 0, 0,
2c82c4dc 1483 process_exit, NULL, &g_array_index(hooks, LttvTraceHook, 8));
9d239bd9 1484 g_assert(!ret);
eed2ef37 1485
9d239bd9 1486 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 1487 LTT_FACILITY_PROCESS, LTT_EVENT_FREE,
1488 LTT_FIELD_PID, 0, 0,
2c82c4dc 1489 process_free, NULL, &g_array_index(hooks, LttvTraceHook, 9));
9d239bd9 1490 g_assert(!ret);
2cdc690b 1491
f4b88a7d 1492 ret = lttv_trace_find_hook(ts->parent.t,
1493 LTT_FACILITY_FS, LTT_EVENT_EXEC,
1494 LTT_FIELD_FILENAME, 0, 0,
1495 process_exec, NULL, &g_array_index(hooks, LttvTraceHook, 10));
1496 g_assert(!ret);
1497
1498
cbe7c836 1499
a5ba1787 1500 /* Add these hooks to each event_by_id hooks list */
dc877563 1501
eed2ef37 1502 nb_tracefile = ts->parent.tracefiles->len;
dbb7bb09 1503
dc877563 1504 for(j = 0 ; j < nb_tracefile ; j++) {
eed2ef37 1505 tfs =
9d239bd9 1506 LTTV_TRACEFILE_STATE(g_array_index(ts->parent.tracefiles,
1507 LttvTracefileContext*, j));
dc877563 1508
1509 for(k = 0 ; k < hooks->len ; k++) {
eed2ef37 1510 hook = &g_array_index(hooks, LttvTraceHook, k);
1511 for(l=0;l<hook->fac_list->len;l++) {
1512 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1513 lttv_hooks_add(
1514 lttv_hooks_by_id_find(tfs->parent.event_by_id, thf->id),
1515 thf->h,
d052ffc3 1516 thf,
eed2ef37 1517 LTTV_PRIO_STATE);
1518 }
ffd54a90 1519 }
dc877563 1520 }
ba576a78 1521 lttv_attribute_find(self->parent.a, LTTV_STATE_HOOKS, LTTV_POINTER, &val);
1522 *(val.v_pointer) = hooks;
dc877563 1523 }
1524}
1525
58c88a41 1526gint lttv_state_hook_remove_event_hooks(void *hook_data, void *call_data)
1527{
1528 LttvTracesetState *tss = (LttvTracesetState*)(call_data);
1529
1530 lttv_state_remove_event_hooks(tss);
1531
1532 return 0;
1533}
dc877563 1534
308711e5 1535void lttv_state_remove_event_hooks(LttvTracesetState *self)
dc877563 1536{
ba576a78 1537 LttvTraceset *traceset = self->parent.ts;
dc877563 1538
eed2ef37 1539 guint i, j, k, l, nb_trace, nb_tracefile;
dc877563 1540
ba576a78 1541 LttvTraceState *ts;
dc877563 1542
ba576a78 1543 LttvTracefileState *tfs;
dc877563 1544
dc877563 1545 GArray *hooks;
1546
eed2ef37 1547 LttvTraceHook *hook;
1548
1549 LttvTraceHookByFacility *thf;
dc877563 1550
1551 LttvAttributeValue val;
1552
ba576a78 1553 nb_trace = lttv_traceset_number(traceset);
dc877563 1554 for(i = 0 ; i < nb_trace ; i++) {
021eeb41 1555 ts = LTTV_TRACE_STATE(self->parent.traces[i]);
ba576a78 1556 lttv_attribute_find(self->parent.a, LTTV_STATE_HOOKS, LTTV_POINTER, &val);
1557 hooks = *(val.v_pointer);
dc877563 1558
a5ba1787 1559 /* Remove these hooks from each event_by_id hooks list */
dc877563 1560
eed2ef37 1561 nb_tracefile = ts->parent.tracefiles->len;
dbb7bb09 1562
dc877563 1563 for(j = 0 ; j < nb_tracefile ; j++) {
eed2ef37 1564 tfs =
cb03932a 1565 LTTV_TRACEFILE_STATE(g_array_index(ts->parent.tracefiles,
1566 LttvTracefileContext*, j));
dc877563 1567
1568 for(k = 0 ; k < hooks->len ; k++) {
eed2ef37 1569 hook = &g_array_index(hooks, LttvTraceHook, k);
1570 for(l=0;l<hook->fac_list->len;l++) {
1571 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1572
1573 lttv_hooks_remove_data(
1574 lttv_hooks_by_id_find(tfs->parent.event_by_id, thf->id),
1575 thf->h,
d052ffc3 1576 thf);
eed2ef37 1577 }
ffd54a90 1578 }
dc877563 1579 }
1986f254 1580 for(k = 0 ; k < hooks->len ; k++)
1581 lttv_trace_hook_destroy(&g_array_index(hooks, LttvTraceHook, k));
dc877563 1582 g_array_free(hooks, TRUE);
1583 }
1584}
1585
eed2ef37 1586static gboolean state_save_event_hook(void *hook_data, void *call_data)
1587{
1588 guint *event_count = (guint*)hook_data;
1589
1590 /* Only save at LTTV_STATE_SAVE_INTERVAL */
1591 if(likely((*event_count)++ < LTTV_STATE_SAVE_INTERVAL))
1592 return FALSE;
1593 else
18c87975 1594 *event_count = 0;
eed2ef37 1595
1596 LttvTracefileState *self = (LttvTracefileState *)call_data;
1597
1598 LttvTracefileState *tfcs;
1599
1600 LttvTraceState *tcs = (LttvTraceState *)(self->parent.t_context);
1601
1602 LttEventPosition *ep;
1603
1604 guint i;
1605
1606 LttTracefile *tf;
1607
1608 LttvAttribute *saved_states_tree, *saved_state_tree;
1609
1610 LttvAttributeValue value;
1611
1612 saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a,
1613 LTTV_STATE_SAVED_STATES);
1614 saved_state_tree = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
1615 value = lttv_attribute_add(saved_states_tree,
1616 lttv_attribute_get_number(saved_states_tree), LTTV_GOBJECT);
1617 *(value.v_gobject) = (GObject *)saved_state_tree;
1618 value = lttv_attribute_add(saved_state_tree, LTTV_STATE_TIME, LTTV_TIME);
1619 *(value.v_time) = self->parent.timestamp;
1620 lttv_state_save(tcs, saved_state_tree);
1621 g_debug("Saving state at time %lu.%lu", self->parent.timestamp.tv_sec,
1622 self->parent.timestamp.tv_nsec);
1623
1624 *(tcs->max_time_state_recomputed_in_seek) = self->parent.timestamp;
1625
1626 return FALSE;
1627}
1628
14aecf75 1629static gboolean state_save_after_trace_hook(void *hook_data, void *call_data)
1630{
1631 LttvTraceState *tcs = (LttvTraceState *)(call_data);
1632
1633 *(tcs->max_time_state_recomputed_in_seek) = tcs->parent.time_span.end_time;
1634
1635 return FALSE;
1636}
1637
eed2ef37 1638#if 0
08b1c66e 1639static gboolean block_start(void *hook_data, void *call_data)
308711e5 1640{
dbb7bb09 1641 LttvTracefileState *self = (LttvTracefileState *)call_data;
308711e5 1642
dbb7bb09 1643 LttvTracefileState *tfcs;
308711e5 1644
dbb7bb09 1645 LttvTraceState *tcs = (LttvTraceState *)(self->parent.t_context);
1646
1647 LttEventPosition *ep;
308711e5 1648
dbb7bb09 1649 guint i, nb_block, nb_event, nb_tracefile;
308711e5 1650
1651 LttTracefile *tf;
1652
1653 LttvAttribute *saved_states_tree, *saved_state_tree;
1654
1655 LttvAttributeValue value;
1656
dbb7bb09 1657 ep = ltt_event_position_new();
eed2ef37 1658
1659 nb_tracefile = tcs->parent.tracefiles->len;
dbb7bb09 1660
1661 /* Count the number of events added since the last block end in any
1662 tracefile. */
1663
1664 for(i = 0 ; i < nb_tracefile ; i++) {
eed2ef37 1665 tfcs =
1666 LTTV_TRACEFILE_STATE(&g_array_index(tcs->parent.tracefiles,
1667 LttvTracefileContext, i));
dbb7bb09 1668 ltt_event_position(tfcs->parent.e, ep);
1669 ltt_event_position_get(ep, &nb_block, &nb_event, &tf);
1670 tcs->nb_event += nb_event - tfcs->saved_position;
1671 tfcs->saved_position = nb_event;
1672 }
1673 g_free(ep);
308711e5 1674
308711e5 1675 if(tcs->nb_event >= tcs->save_interval) {
1676 saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a,
1677 LTTV_STATE_SAVED_STATES);
1678 saved_state_tree = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
1679 value = lttv_attribute_add(saved_states_tree,
1680 lttv_attribute_get_number(saved_states_tree), LTTV_GOBJECT);
1681 *(value.v_gobject) = (GObject *)saved_state_tree;
1682 value = lttv_attribute_add(saved_state_tree, LTTV_STATE_TIME, LTTV_TIME);
dbb7bb09 1683 *(value.v_time) = self->parent.timestamp;
308711e5 1684 lttv_state_save(tcs, saved_state_tree);
1685 tcs->nb_event = 0;
08b1c66e 1686 g_debug("Saving state at time %lu.%lu", self->parent.timestamp.tv_sec,
1687 self->parent.timestamp.tv_nsec);
308711e5 1688 }
dbb7bb09 1689 *(tcs->max_time_state_recomputed_in_seek) = self->parent.timestamp;
308711e5 1690 return FALSE;
1691}
eed2ef37 1692#endif //0
308711e5 1693
eed2ef37 1694#if 0
08b1c66e 1695static gboolean block_end(void *hook_data, void *call_data)
1696{
1697 LttvTracefileState *self = (LttvTracefileState *)call_data;
1698
1699 LttvTraceState *tcs = (LttvTraceState *)(self->parent.t_context);
1700
1701 LttTracefile *tf;
1702
1703 LttEventPosition *ep;
1704
1705 guint nb_block, nb_event;
1706
1707 ep = ltt_event_position_new();
1708 ltt_event_position(self->parent.e, ep);
1709 ltt_event_position_get(ep, &nb_block, &nb_event, &tf);
1710 tcs->nb_event += nb_event - self->saved_position + 1;
1711 self->saved_position = 0;
1712 *(tcs->max_time_state_recomputed_in_seek) = self->parent.timestamp;
1713 g_free(ep);
00e74b69 1714
1715 return FALSE;
08b1c66e 1716}
eed2ef37 1717#endif //0
1718#if 0
308711e5 1719void lttv_state_save_add_event_hooks(LttvTracesetState *self)
1720{
1721 LttvTraceset *traceset = self->parent.ts;
1722
00e74b69 1723 guint i, j, nb_trace, nb_tracefile;
308711e5 1724
1725 LttvTraceState *ts;
1726
1727 LttvTracefileState *tfs;
1728
08b1c66e 1729 LttvTraceHook hook_start, hook_end;
308711e5 1730
1731 nb_trace = lttv_traceset_number(traceset);
1732 for(i = 0 ; i < nb_trace ; i++) {
1733 ts = (LttvTraceState *)self->parent.traces[i];
eed2ef37 1734
08b1c66e 1735 lttv_trace_find_hook(ts->parent.t, "core","block_start",NULL,
1736 NULL, NULL, block_start, &hook_start);
308711e5 1737 lttv_trace_find_hook(ts->parent.t, "core","block_end",NULL,
08b1c66e 1738 NULL, NULL, block_end, &hook_end);
308711e5 1739
eed2ef37 1740 nb_tracefile = ts->parent.tracefiles->len;
308711e5 1741
dbb7bb09 1742 for(j = 0 ; j < nb_tracefile ; j++) {
eed2ef37 1743 tfs =
1744 LTTV_TRACEFILE_STATE(&g_array_index(ts->parent.tracefiles,
1745 LttvTracefileContext, j));
a5ba1787 1746 lttv_hooks_add(lttv_hooks_by_id_find(tfs->parent.event_by_id,
eed2ef37 1747 hook_start.id), hook_start.h, NULL, LTTV_PRIO_STATE);
a5ba1787 1748 lttv_hooks_add(lttv_hooks_by_id_find(tfs->parent.event_by_id,
eed2ef37 1749 hook_end.id), hook_end.h, NULL, LTTV_PRIO_STATE);
1750 }
1751 }
1752}
1753#endif //0
1754
1755void lttv_state_save_add_event_hooks(LttvTracesetState *self)
1756{
1757 LttvTraceset *traceset = self->parent.ts;
1758
1759 guint i, j, nb_trace, nb_tracefile;
1760
1761 LttvTraceState *ts;
1762
1763 LttvTracefileState *tfs;
1764
1765
1766 nb_trace = lttv_traceset_number(traceset);
1767 for(i = 0 ; i < nb_trace ; i++) {
1768
1769 ts = (LttvTraceState *)self->parent.traces[i];
1770 nb_tracefile = ts->parent.tracefiles->len;
1771
3054461a 1772 guint *event_count = g_new(guint, 1);
1773 *event_count = 0;
1774
eed2ef37 1775 for(j = 0 ; j < nb_tracefile ; j++) {
1776 tfs =
cb03932a 1777 LTTV_TRACEFILE_STATE(g_array_index(ts->parent.tracefiles,
1778 LttvTracefileContext*, j));
eed2ef37 1779 lttv_hooks_add(tfs->parent.event,
1780 state_save_event_hook,
1781 event_count,
1782 LTTV_PRIO_STATE);
1783
308711e5 1784 }
1785 }
14aecf75 1786
1787 lttv_process_traceset_begin(&self->parent,
1788 NULL, NULL, NULL, NULL, NULL);
1789
308711e5 1790}
1791
b56b5fec 1792gint lttv_state_save_hook_add_event_hooks(void *hook_data, void *call_data)
1793{
1794 LttvTracesetState *tss = (LttvTracesetState*)(call_data);
1795
1796 lttv_state_save_add_event_hooks(tss);
1797
1798 return 0;
1799}
1800
308711e5 1801
eed2ef37 1802#if 0
308711e5 1803void lttv_state_save_remove_event_hooks(LttvTracesetState *self)
1804{
1805 LttvTraceset *traceset = self->parent.ts;
1806
00e74b69 1807 guint i, j, nb_trace, nb_tracefile;
308711e5 1808
1809 LttvTraceState *ts;
1810
1811 LttvTracefileState *tfs;
1812
08b1c66e 1813 LttvTraceHook hook_start, hook_end;
308711e5 1814
1815 nb_trace = lttv_traceset_number(traceset);
1816 for(i = 0 ; i < nb_trace ; i++) {
1817 ts = LTTV_TRACE_STATE(self->parent.traces[i]);
eed2ef37 1818
08b1c66e 1819 lttv_trace_find_hook(ts->parent.t, "core","block_start",NULL,
1820 NULL, NULL, block_start, &hook_start);
1821
308711e5 1822 lttv_trace_find_hook(ts->parent.t, "core","block_end",NULL,
08b1c66e 1823 NULL, NULL, block_end, &hook_end);
308711e5 1824
eed2ef37 1825 nb_tracefile = ts->parent.tracefiles->len;
308711e5 1826
dbb7bb09 1827 for(j = 0 ; j < nb_tracefile ; j++) {
eed2ef37 1828 tfs =
1829 LTTV_TRACEFILE_STATE(&g_array_index(ts->parent.tracefiles,
1830 LttvTracefileContext, j));
308711e5 1831 lttv_hooks_remove_data(lttv_hooks_by_id_find(
a5ba1787 1832 tfs->parent.event_by_id, hook_start.id), hook_start.h, NULL);
08b1c66e 1833 lttv_hooks_remove_data(lttv_hooks_by_id_find(
a5ba1787 1834 tfs->parent.event_by_id, hook_end.id), hook_end.h, NULL);
308711e5 1835 }
1836 }
1837}
eed2ef37 1838#endif //0
1839
1840void lttv_state_save_remove_event_hooks(LttvTracesetState *self)
1841{
1842 LttvTraceset *traceset = self->parent.ts;
1843
1844 guint i, j, nb_trace, nb_tracefile;
1845
1846 LttvTraceState *ts;
1847
1848 LttvTracefileState *tfs;
1849
14aecf75 1850 LttvHooks *after_trace = lttv_hooks_new();
1851
1852 lttv_hooks_add(after_trace,
1853 state_save_after_trace_hook,
1854 NULL,
1855 LTTV_PRIO_STATE);
1856
1857
1858 lttv_process_traceset_end(&self->parent,
1859 NULL, after_trace, NULL, NULL, NULL);
eed2ef37 1860
14aecf75 1861 lttv_hooks_destroy(after_trace);
1862
eed2ef37 1863 nb_trace = lttv_traceset_number(traceset);
1864 for(i = 0 ; i < nb_trace ; i++) {
1865
1866 ts = (LttvTraceState *)self->parent.traces[i];
1867 nb_tracefile = ts->parent.tracefiles->len;
1868
22b165e9 1869 guint *event_count = NULL;
eed2ef37 1870
1871 for(j = 0 ; j < nb_tracefile ; j++) {
1872 tfs =
cb03932a 1873 LTTV_TRACEFILE_STATE(g_array_index(ts->parent.tracefiles,
1874 LttvTracefileContext*, j));
eed2ef37 1875 event_count = lttv_hooks_remove(tfs->parent.event,
1876 state_save_event_hook);
eed2ef37 1877 }
22b165e9 1878 if(event_count) g_free(event_count);
eed2ef37 1879 }
1880}
308711e5 1881
b56b5fec 1882gint lttv_state_save_hook_remove_event_hooks(void *hook_data, void *call_data)
1883{
1884 LttvTracesetState *tss = (LttvTracesetState*)(call_data);
1885
1886 lttv_state_save_remove_event_hooks(tss);
1887
1888 return 0;
1889}
308711e5 1890
dd025f91 1891void lttv_state_traceset_seek_time_closest(LttvTracesetState *self, LttTime t)
308711e5 1892{
1893 LttvTraceset *traceset = self->parent.ts;
1894
00e74b69 1895 guint i, nb_trace;
308711e5 1896
1897 int min_pos, mid_pos, max_pos;
1898
728d0c3e 1899 guint call_rest = 0;
1900
308711e5 1901 LttvTraceState *tcs;
1902
1903 LttvAttributeValue value;
1904
1905 LttvAttributeType type;
1906
1907 LttvAttributeName name;
1908
1909 LttvAttribute *saved_states_tree, *saved_state_tree, *closest_tree;
1910
d448fce2 1911 //g_tree_destroy(self->parent.pqueue);
1912 //self->parent.pqueue = g_tree_new(compare_tracefile);
348c6ba8 1913
728d0c3e 1914 g_info("Entering seek_time_closest for time %lu.%lu", t.tv_sec, t.tv_nsec);
1915
308711e5 1916 nb_trace = lttv_traceset_number(traceset);
1917 for(i = 0 ; i < nb_trace ; i++) {
1918 tcs = (LttvTraceState *)self->parent.traces[i];
1919
2a2fa4f0 1920 if(ltt_time_compare(t, *(tcs->max_time_state_recomputed_in_seek)) < 0) {
1921 saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a,
1922 LTTV_STATE_SAVED_STATES);
1923 min_pos = -1;
1924
1925 if(saved_states_tree) {
dd025f91 1926 max_pos = lttv_attribute_get_number(saved_states_tree) - 1;
1927 mid_pos = max_pos / 2;
1928 while(min_pos < max_pos) {
1929 type = lttv_attribute_get(saved_states_tree, mid_pos, &name, &value);
1930 g_assert(type == LTTV_GOBJECT);
1931 saved_state_tree = *((LttvAttribute **)(value.v_gobject));
1932 type = lttv_attribute_get_by_name(saved_state_tree, LTTV_STATE_TIME,
1933 &value);
1934 g_assert(type == LTTV_TIME);
1935 if(ltt_time_compare(*(value.v_time), t) < 0) {
1936 min_pos = mid_pos;
1937 closest_tree = saved_state_tree;
1938 }
1939 else max_pos = mid_pos - 1;
1940
1941 mid_pos = (min_pos + max_pos + 1) / 2;
1942 }
2a2fa4f0 1943 }
dd025f91 1944
2a2fa4f0 1945 /* restore the closest earlier saved state */
f95bc830 1946 if(min_pos != -1) {
1947 lttv_state_restore(tcs, closest_tree);
728d0c3e 1948 call_rest = 1;
f95bc830 1949 }
dd025f91 1950
2a2fa4f0 1951 /* There is no saved state, yet we want to have it. Restart at T0 */
dd025f91 1952 else {
1953 restore_init_state(tcs);
1954 lttv_process_trace_seek_time(&(tcs->parent), ltt_time_zero);
308711e5 1955 }
9444deae 1956 }
dd025f91 1957 /* We want to seek quickly without restoring/updating the state */
1958 else {
308711e5 1959 restore_init_state(tcs);
dd025f91 1960 lttv_process_trace_seek_time(&(tcs->parent), t);
308711e5 1961 }
308711e5 1962 }
728d0c3e 1963 if(!call_rest) g_info("NOT Calling restore");
308711e5 1964}
1965
1966
1967static void
1968traceset_state_instance_init (GTypeInstance *instance, gpointer g_class)
1969{
1970}
1971
1972
1973static void
1974traceset_state_finalize (LttvTracesetState *self)
1975{
1976 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))->
1977 finalize(G_OBJECT(self));
1978}
1979
1980
1981static void
1982traceset_state_class_init (LttvTracesetContextClass *klass)
1983{
1984 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
1985
1986 gobject_class->finalize = (void (*)(GObject *self)) traceset_state_finalize;
1987 klass->init = (void (*)(LttvTracesetContext *self, LttvTraceset *ts))init;
1988 klass->fini = (void (*)(LttvTracesetContext *self))fini;
1989 klass->new_traceset_context = new_traceset_context;
1990 klass->new_trace_context = new_trace_context;
1991 klass->new_tracefile_context = new_tracefile_context;
1992}
1993
1994
1995GType
1996lttv_traceset_state_get_type(void)
1997{
1998 static GType type = 0;
1999 if (type == 0) {
2000 static const GTypeInfo info = {
2001 sizeof (LttvTracesetStateClass),
2002 NULL, /* base_init */
2003 NULL, /* base_finalize */
2004 (GClassInitFunc) traceset_state_class_init, /* class_init */
2005 NULL, /* class_finalize */
2006 NULL, /* class_data */
dbb7bb09 2007 sizeof (LttvTracesetState),
308711e5 2008 0, /* n_preallocs */
00e74b69 2009 (GInstanceInitFunc) traceset_state_instance_init, /* instance_init */
2010 NULL /* value handling */
308711e5 2011 };
2012
2013 type = g_type_register_static (LTTV_TRACESET_CONTEXT_TYPE, "LttvTracesetStateType",
2014 &info, 0);
2015 }
2016 return type;
2017}
2018
2019
2020static void
2021trace_state_instance_init (GTypeInstance *instance, gpointer g_class)
2022{
2023}
2024
2025
2026static void
2027trace_state_finalize (LttvTraceState *self)
2028{
2029 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_CONTEXT_TYPE))->
2030 finalize(G_OBJECT(self));
2031}
2032
2033
2034static void
2035trace_state_class_init (LttvTraceStateClass *klass)
2036{
2037 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
2038
2039 gobject_class->finalize = (void (*)(GObject *self)) trace_state_finalize;
2040 klass->state_save = state_save;
2041 klass->state_restore = state_restore;
2042 klass->state_saved_free = state_saved_free;
2043}
2044
2045
2046GType
2047lttv_trace_state_get_type(void)
2048{
2049 static GType type = 0;
2050 if (type == 0) {
2051 static const GTypeInfo info = {
2052 sizeof (LttvTraceStateClass),
2053 NULL, /* base_init */
2054 NULL, /* base_finalize */
2055 (GClassInitFunc) trace_state_class_init, /* class_init */
2056 NULL, /* class_finalize */
2057 NULL, /* class_data */
2058 sizeof (LttvTraceState),
2059 0, /* n_preallocs */
00e74b69 2060 (GInstanceInitFunc) trace_state_instance_init, /* instance_init */
2061 NULL /* value handling */
308711e5 2062 };
2063
2064 type = g_type_register_static (LTTV_TRACE_CONTEXT_TYPE,
2065 "LttvTraceStateType", &info, 0);
2066 }
2067 return type;
2068}
2069
2070
2071static void
2072tracefile_state_instance_init (GTypeInstance *instance, gpointer g_class)
2073{
2074}
2075
2076
2077static void
2078tracefile_state_finalize (LttvTracefileState *self)
2079{
2080 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_CONTEXT_TYPE))->
2081 finalize(G_OBJECT(self));
2082}
2083
2084
2085static void
2086tracefile_state_class_init (LttvTracefileStateClass *klass)
2087{
2088 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
2089
2090 gobject_class->finalize = (void (*)(GObject *self)) tracefile_state_finalize;
2091}
2092
2093
2094GType
2095lttv_tracefile_state_get_type(void)
2096{
2097 static GType type = 0;
2098 if (type == 0) {
2099 static const GTypeInfo info = {
2100 sizeof (LttvTracefileStateClass),
2101 NULL, /* base_init */
2102 NULL, /* base_finalize */
2103 (GClassInitFunc) tracefile_state_class_init, /* class_init */
2104 NULL, /* class_finalize */
2105 NULL, /* class_data */
2106 sizeof (LttvTracefileState),
2107 0, /* n_preallocs */
00e74b69 2108 (GInstanceInitFunc) tracefile_state_instance_init, /* instance_init */
2109 NULL /* value handling */
308711e5 2110 };
2111
2112 type = g_type_register_static (LTTV_TRACEFILE_CONTEXT_TYPE,
2113 "LttvTracefileStateType", &info, 0);
2114 }
2115 return type;
2116}
2117
2118
08b1c66e 2119static void module_init()
ffd54a90 2120{
2121 LTTV_STATE_UNNAMED = g_quark_from_string("unnamed");
b445142a 2122 LTTV_STATE_MODE_UNKNOWN = g_quark_from_string("unknown execution mode");
ffd54a90 2123 LTTV_STATE_USER_MODE = g_quark_from_string("user mode");
2124 LTTV_STATE_WAIT_FORK = g_quark_from_string("wait fork");
2125 LTTV_STATE_SYSCALL = g_quark_from_string("system call");
2126 LTTV_STATE_TRAP = g_quark_from_string("trap");
2127 LTTV_STATE_IRQ = g_quark_from_string("irq");
b445142a 2128 LTTV_STATE_SUBMODE_UNKNOWN = g_quark_from_string("unknown submode");
2129 LTTV_STATE_SUBMODE_NONE = g_quark_from_string("(no submode)");
ffd54a90 2130 LTTV_STATE_WAIT_CPU = g_quark_from_string("wait for cpu");
dbd243b1 2131 LTTV_STATE_EXIT = g_quark_from_string("exiting");
0828099d 2132 LTTV_STATE_ZOMBIE = g_quark_from_string("zombie");
ffd54a90 2133 LTTV_STATE_WAIT = g_quark_from_string("wait for I/O");
2134 LTTV_STATE_RUN = g_quark_from_string("running");
791dffa6 2135 LTTV_STATE_DEAD = g_quark_from_string("dead");
308711e5 2136 LTTV_STATE_TRACEFILES = g_quark_from_string("tracefiles");
2137 LTTV_STATE_PROCESSES = g_quark_from_string("processes");
2138 LTTV_STATE_PROCESS = g_quark_from_string("process");
348c6ba8 2139 LTTV_STATE_RUNNING_PROCESS = g_quark_from_string("running_process");
308711e5 2140 LTTV_STATE_EVENT = g_quark_from_string("event");
2141 LTTV_STATE_SAVED_STATES = g_quark_from_string("saved states");
dbb7bb09 2142 LTTV_STATE_SAVED_STATES_TIME = g_quark_from_string("saved states time");
308711e5 2143 LTTV_STATE_TIME = g_quark_from_string("time");
ffd54a90 2144 LTTV_STATE_HOOKS = g_quark_from_string("saved state hooks");
f95bc830 2145 LTTV_STATE_NAME_TABLES = g_quark_from_string("name tables");
2146 LTTV_STATE_TRACE_STATE_USE_COUNT =
2147 g_quark_from_string("trace_state_use_count");
eed2ef37 2148
2149
2150 LTT_FACILITY_KERNEL = g_quark_from_string("kernel");
2151 LTT_FACILITY_PROCESS = g_quark_from_string("process");
f4b88a7d 2152 LTT_FACILITY_FS = g_quark_from_string("fs");
eed2ef37 2153
2154
2155 LTT_EVENT_SYSCALL_ENTRY = g_quark_from_string("syscall_entry");
2156 LTT_EVENT_SYSCALL_EXIT = g_quark_from_string("syscall_exit");
2157 LTT_EVENT_TRAP_ENTRY = g_quark_from_string("trap_entry");
2158 LTT_EVENT_TRAP_EXIT = g_quark_from_string("trap_exit");
2159 LTT_EVENT_IRQ_ENTRY = g_quark_from_string("irq_entry");
2160 LTT_EVENT_IRQ_EXIT = g_quark_from_string("irq_exit");
2161 LTT_EVENT_SCHEDCHANGE = g_quark_from_string("schedchange");
2162 LTT_EVENT_FORK = g_quark_from_string("fork");
2163 LTT_EVENT_EXIT = g_quark_from_string("exit");
2164 LTT_EVENT_FREE = g_quark_from_string("free");
f4b88a7d 2165 LTT_EVENT_EXEC = g_quark_from_string("exec");
eed2ef37 2166
2167
2168 LTT_FIELD_SYSCALL_ID = g_quark_from_string("syscall_id");
2169 LTT_FIELD_TRAP_ID = g_quark_from_string("trap_id");
2170 LTT_FIELD_IRQ_ID = g_quark_from_string("irq_id");
2171 LTT_FIELD_OUT = g_quark_from_string("out");
2172 LTT_FIELD_IN = g_quark_from_string("in");
2173 LTT_FIELD_OUT_STATE = g_quark_from_string("out_state");
2174 LTT_FIELD_PARENT_PID = g_quark_from_string("parent_pid");
2175 LTT_FIELD_CHILD_PID = g_quark_from_string("child_pid");
2176 LTT_FIELD_PID = g_quark_from_string("pid");
f4b88a7d 2177 LTT_FIELD_FILENAME = g_quark_from_string("filename");
eed2ef37 2178
ffd54a90 2179}
dc877563 2180
08b1c66e 2181static void module_destroy()
ffd54a90 2182{
2183}
dc877563 2184
2185
08b1c66e 2186LTTV_MODULE("state", "State computation", \
2187 "Update the system state, possibly saving it at intervals", \
2188 module_init, module_destroy)
2189
dc877563 2190
2191
This page took 0.151088 seconds and 4 git commands to generate.