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