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