use enums arch specific for syscall names
[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,
7b143580 38 LTT_FACILITY_ASM_I386_KERNEL,
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,
7b143580 772 LTT_FACILITY_ASM_I386_KERNEL, 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);
2312de30 780 //nb = ltt_type_element_number(t);
eed2ef37 781
021eeb41 782 lttv_trace_hook_destroy(&h);
b445142a 783
eed2ef37 784 /* CHECK syscalls should be an enum but currently are not!
f95bc830 785 name_tables->syscall_names = g_new(GQuark, nb);
b445142a 786
787 for(i = 0 ; i < nb ; i++) {
f95bc830 788 name_tables->syscall_names[i] = g_quark_from_string(
789 ltt_enum_string_get(t, i));
b445142a 790 }
791 */
792
f95bc830 793 name_tables->syscall_names = g_new(GQuark, 256);
b445142a 794 for(i = 0 ; i < 256 ; i++) {
795 g_string_printf(fe_name, "syscall %d", i);
f95bc830 796 name_tables->syscall_names[i] = g_quark_from_string(fe_name->str);
b445142a 797 }
798
eed2ef37 799 if(lttv_trace_find_hook(tcs->parent.t, LTT_FACILITY_KERNEL,
800 LTT_EVENT_TRAP_ENTRY,
801 LTT_FIELD_TRAP_ID, 0, 0,
2c82c4dc 802 NULL, NULL, &h))
eed2ef37 803 return;
804
021eeb41 805 thf = lttv_trace_hook_get_first(&h);
eed2ef37 806
807 t = ltt_field_type(thf->f1);
2312de30 808 //nb = ltt_type_element_number(t);
b445142a 809
021eeb41 810 lttv_trace_hook_destroy(&h);
eed2ef37 811
b445142a 812 /*
f95bc830 813 name_tables->trap_names = g_new(GQuark, nb);
b445142a 814 for(i = 0 ; i < nb ; i++) {
f95bc830 815 name_tables->trap_names[i] = g_quark_from_string(
816 ltt_enum_string_get(t, i));
b445142a 817 }
818 */
819
f95bc830 820 name_tables->trap_names = g_new(GQuark, 256);
b445142a 821 for(i = 0 ; i < 256 ; i++) {
822 g_string_printf(fe_name, "trap %d", i);
f95bc830 823 name_tables->trap_names[i] = g_quark_from_string(fe_name->str);
b445142a 824 }
825
eed2ef37 826 if(lttv_trace_find_hook(tcs->parent.t,
827 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
828 LTT_FIELD_IRQ_ID, 0, 0,
2c82c4dc 829 NULL, NULL, &h))
eed2ef37 830 return;
831
021eeb41 832 thf = lttv_trace_hook_get_first(&h);
eed2ef37 833
834 t = ltt_field_type(thf->f1);
2312de30 835 //nb = ltt_type_element_number(t);
b445142a 836
021eeb41 837 lttv_trace_hook_destroy(&h);
eed2ef37 838
b445142a 839 /*
f95bc830 840 name_tables->irq_names = g_new(GQuark, nb);
b445142a 841 for(i = 0 ; i < nb ; i++) {
f95bc830 842 name_tables->irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
b445142a 843 }
844 */
845
f95bc830 846 name_tables->irq_names = g_new(GQuark, 256);
b445142a 847 for(i = 0 ; i < 256 ; i++) {
848 g_string_printf(fe_name, "irq %d", i);
f95bc830 849 name_tables->irq_names[i] = g_quark_from_string(fe_name->str);
b445142a 850 }
851
852 g_string_free(fe_name, TRUE);
853}
854
855
f95bc830 856static void
857get_name_tables(LttvTraceState *tcs)
858{
859 LttvNameTables *name_tables;
860
861 LttvAttributeValue v;
862
863 lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_NAME_TABLES,
864 LTTV_POINTER, &v);
865 g_assert(*(v.v_pointer) != NULL);
866 name_tables = (LttvNameTables *)*(v.v_pointer);
eed2ef37 867 //tcs->eventtype_names = name_tables->eventtype_names;
f95bc830 868 tcs->syscall_names = name_tables->syscall_names;
869 tcs->trap_names = name_tables->trap_names;
870 tcs->irq_names = name_tables->irq_names;
871}
872
873
b445142a 874static void
875free_name_tables(LttvTraceState *tcs)
876{
f95bc830 877 LttvNameTables *name_tables;
878
879 LttvAttributeValue v;
880
881 lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_NAME_TABLES,
882 LTTV_POINTER, &v);
883 name_tables = (LttvNameTables *)*(v.v_pointer);
884 *(v.v_pointer) = NULL;
885
eed2ef37 886 // g_free(name_tables->eventtype_names);
f95bc830 887 g_free(name_tables->syscall_names);
888 g_free(name_tables->trap_names);
889 g_free(name_tables->irq_names);
890 g_free(name_tables);
b445142a 891}
dc877563 892
15b3d537 893#ifdef HASH_TABLE_DEBUG
894
895static void test_process(gpointer key, gpointer value, gpointer user_data)
896{
897 LttvProcessState *process = (LttvProcessState *)value;
898
899 /* Test for process corruption */
900 guint stack_len = process->execution_stack->len;
901}
902
903static void hash_table_check(GHashTable *table)
904{
905 g_hash_table_foreach(table, test_process, NULL);
906}
907
908
909#endif
910
911
b445142a 912static void push_state(LttvTracefileState *tfs, LttvExecutionMode t,
ffd54a90 913 guint state_id)
dc877563 914{
b445142a 915 LttvExecutionState *es;
348c6ba8 916
917 guint cpu = ltt_tracefile_num(tfs->parent.tf);
918 LttvTraceState *ts = (LttvTraceState*)tfs->parent.t_context;
15b3d537 919
920#ifdef HASH_TABLE_DEBUG
921 hash_table_check(ts->processes);
922#endif
348c6ba8 923 LttvProcessState *process = ts->running_process[cpu];
dc877563 924
b445142a 925 guint depth = process->execution_stack->len;
dc877563 926
e05fc742 927 process->execution_stack =
928 g_array_set_size(process->execution_stack, depth + 1);
929 /* Keep in sync */
930 process->state =
931 &g_array_index(process->execution_stack, LttvExecutionState, depth - 1);
932
b445142a 933 es = &g_array_index(process->execution_stack, LttvExecutionState, depth);
934 es->t = t;
935 es->n = state_id;
936 es->entry = es->change = tfs->parent.timestamp;
937 es->s = process->state->s;
938 process->state = es;
dc877563 939}
940
941
b445142a 942static void pop_state(LttvTracefileState *tfs, LttvExecutionMode t)
dc877563 943{
348c6ba8 944 guint cpu = ltt_tracefile_num(tfs->parent.tf);
945 LttvTraceState *ts = (LttvTraceState*)tfs->parent.t_context;
946 LttvProcessState *process = ts->running_process[cpu];
dc877563 947
f95bc830 948 guint depth = process->execution_stack->len;
dc877563 949
3d27549e 950 if(process->state->t != t){
00e74b69 951 g_info("Different execution mode type (%lu.%09lu): ignore it\n",
b445142a 952 tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec);
08b1c66e 953 g_info("process state has %s when pop_int is %s\n",
8e8e6b64 954 g_quark_to_string(process->state->t),
955 g_quark_to_string(t));
08b1c66e 956 g_info("{ %u, %u, %s, %s }\n",
8e8e6b64 957 process->pid,
958 process->ppid,
959 g_quark_to_string(process->name),
960 g_quark_to_string(process->state->s));
3d27549e 961 return;
962 }
b445142a 963
f95bc830 964 if(depth == 1){
00e74b69 965 g_info("Trying to pop last state on stack (%lu.%09lu): ignore it\n",
b445142a 966 tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec);
967 return;
968 }
969
e05fc742 970 process->execution_stack =
971 g_array_set_size(process->execution_stack, depth - 1);
b445142a 972 process->state = &g_array_index(process->execution_stack, LttvExecutionState,
f95bc830 973 depth - 2);
b445142a 974 process->state->change = tfs->parent.timestamp;
dc877563 975}
976
977
2a2fa4f0 978LttvProcessState *
348c6ba8 979lttv_state_create_process(LttvTraceState *tcs, LttvProcessState *parent,
980 guint cpu, guint pid, const LttTime *timestamp)
dc877563 981{
982 LttvProcessState *process = g_new(LttvProcessState, 1);
983
b445142a 984 LttvExecutionState *es;
dc877563 985
348c6ba8 986 LttvTraceContext *tc = (LttvTraceContext*)tcs;
ba576a78 987
b445142a 988 char buffer[128];
ffd54a90 989
dc877563 990 process->pid = pid;
348c6ba8 991 process->cpu = cpu;
992 //process->last_cpu = tfs->cpu_name;
993 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
cb03932a 994 g_info("Process %u, core %p", process->pid, process);
2a2fa4f0 995 g_hash_table_insert(tcs->processes, process, process);
b445142a 996
997 if(parent) {
998 process->ppid = parent->pid;
999 process->name = parent->name;
348c6ba8 1000 process->creation_time = *timestamp;
b445142a 1001 }
2a2fa4f0 1002
1003 /* No parent. This process exists but we are missing all information about
1004 its creation. The birth time is set to zero but we remember the time of
1005 insertion */
1006
b445142a 1007 else {
1008 process->ppid = 0;
1009 process->name = LTTV_STATE_UNNAMED;
2a2fa4f0 1010 process->creation_time = ltt_time_zero;
b445142a 1011 }
1012
348c6ba8 1013 process->insertion_time = *timestamp;
b445142a 1014 sprintf(buffer,"%d-%lu.%lu",pid, process->creation_time.tv_sec,
1015 process->creation_time.tv_nsec);
1016 process->pid_time = g_quark_from_string(buffer);
348c6ba8 1017 process->cpu = cpu;
1018 //process->last_cpu = tfs->cpu_name;
1019 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
e8f2280c 1020 process->execution_stack = g_array_sized_new(FALSE, FALSE,
1021 sizeof(LttvExecutionState), PREALLOCATED_EXECUTION_STACK);
c607371b 1022 process->execution_stack = g_array_set_size(process->execution_stack, 2);
b445142a 1023 es = process->state = &g_array_index(process->execution_stack,
1024 LttvExecutionState, 0);
1025 es->t = LTTV_STATE_USER_MODE;
1026 es->n = LTTV_STATE_SUBMODE_NONE;
348c6ba8 1027 es->entry = *timestamp;
1028 //g_assert(timestamp->tv_sec != 0);
1029 es->change = *timestamp;
c607371b 1030 es->s = LTTV_STATE_RUN;
1031
1032 es = process->state = &g_array_index(process->execution_stack,
1033 LttvExecutionState, 1);
1034 es->t = LTTV_STATE_SYSCALL;
1035 es->n = LTTV_STATE_SUBMODE_NONE;
1036 es->entry = *timestamp;
1037 //g_assert(timestamp->tv_sec != 0);
1038 es->change = *timestamp;
b445142a 1039 es->s = LTTV_STATE_WAIT_FORK;
cbe7c836 1040
1041 return process;
dc877563 1042}
1043
348c6ba8 1044LttvProcessState *lttv_state_find_process(LttvTraceState *ts, guint cpu,
41c7f803 1045 guint pid)
dc877563 1046{
2a2fa4f0 1047 LttvProcessState key;
1048 LttvProcessState *process;
1049
1050 key.pid = pid;
348c6ba8 1051 key.cpu = cpu;
2a2fa4f0 1052 process = g_hash_table_lookup(ts->processes, &key);
dc877563 1053 return process;
1054}
1055
2a2fa4f0 1056LttvProcessState *
348c6ba8 1057lttv_state_find_process_or_create(LttvTraceState *ts, guint cpu, guint pid,
1058 LttTime *timestamp)
2a2fa4f0 1059{
348c6ba8 1060 LttvProcessState *process = lttv_state_find_process(ts, cpu, pid);
1061
1062 /* Put ltt_time_zero creation time for unexisting processes */
1063 if(unlikely(process == NULL)) process = lttv_state_create_process(ts,
1064 NULL, cpu, pid, timestamp);
2a2fa4f0 1065 return process;
1066}
1067
41c7f803 1068/* FIXME : this function should be called when we receive an event telling that
1069 * release_task has been called in the kernel. In happens generally when
1070 * the parent waits for its child terminaison, but may also happen in special
1071 * cases in the child's exit : when the parent ignores its children SIGCCHLD or
1072 * has the flag SA_NOCLDWAIT. It can also happen when the child is part
1073 * of a killed thread ground, but isn't the leader.
41c7f803 1074 */
b445142a 1075static void exit_process(LttvTracefileState *tfs, LttvProcessState *process)
dc877563 1076{
ba576a78 1077 LttvTraceState *ts = LTTV_TRACE_STATE(tfs->parent.t_context);
2a2fa4f0 1078 LttvProcessState key;
ba576a78 1079
2a2fa4f0 1080 key.pid = process->pid;
348c6ba8 1081 key.cpu = process->cpu;
2a2fa4f0 1082 g_hash_table_remove(ts->processes, &key);
b445142a 1083 g_array_free(process->execution_stack, TRUE);
dc877563 1084 g_free(process);
1085}
1086
1087
b445142a 1088static void free_process_state(gpointer key, gpointer value,gpointer user_data)
dc877563 1089{
b445142a 1090 g_array_free(((LttvProcessState *)value)->execution_stack, TRUE);
dc877563 1091 g_free(value);
1092}
1093
1094
308711e5 1095static void lttv_state_free_process_table(GHashTable *processes)
dc877563 1096{
1097 g_hash_table_foreach(processes, free_process_state, NULL);
308711e5 1098 g_hash_table_destroy(processes);
dc877563 1099}
1100
1101
b445142a 1102static gboolean syscall_entry(void *hook_data, void *call_data)
dc877563 1103{
ba576a78 1104 LttvTracefileState *s = (LttvTracefileState *)call_data;
eed2ef37 1105 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
d052ffc3 1106 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
eed2ef37 1107 LttField *f = thf->f1;
dc877563 1108
b445142a 1109 LttvExecutionSubmode submode;
1110
1111 submode = ((LttvTraceState *)(s->parent.t_context))->syscall_names[
eed2ef37 1112 ltt_event_get_unsigned(e, f)];
b445142a 1113 push_state(s, LTTV_STATE_SYSCALL, submode);
dc877563 1114 return FALSE;
1115}
1116
1117
b445142a 1118static gboolean syscall_exit(void *hook_data, void *call_data)
dc877563 1119{
ba576a78 1120 LttvTracefileState *s = (LttvTracefileState *)call_data;
dc877563 1121
ffd54a90 1122 pop_state(s, LTTV_STATE_SYSCALL);
dc877563 1123 return FALSE;
1124}
1125
1126
b445142a 1127static gboolean trap_entry(void *hook_data, void *call_data)
dc877563 1128{
ba576a78 1129 LttvTracefileState *s = (LttvTracefileState *)call_data;
eed2ef37 1130 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
d052ffc3 1131 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
eed2ef37 1132 LttField *f = thf->f1;
dc877563 1133
b445142a 1134 LttvExecutionSubmode submode;
1135
1136 submode = ((LttvTraceState *)(s->parent.t_context))->trap_names[
eed2ef37 1137 ltt_event_get_unsigned(e, f)];
b445142a 1138 push_state(s, LTTV_STATE_TRAP, submode);
dc877563 1139 return FALSE;
1140}
1141
1142
b445142a 1143static gboolean trap_exit(void *hook_data, void *call_data)
dc877563 1144{
ba576a78 1145 LttvTracefileState *s = (LttvTracefileState *)call_data;
dc877563 1146
ffd54a90 1147 pop_state(s, LTTV_STATE_TRAP);
dc877563 1148 return FALSE;
1149}
1150
1151
b445142a 1152static gboolean irq_entry(void *hook_data, void *call_data)
dc877563 1153{
ba576a78 1154 LttvTracefileState *s = (LttvTracefileState *)call_data;
eed2ef37 1155 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
9d239bd9 1156 guint8 fac_id = ltt_event_facility_id(e);
1157 guint8 ev_id = ltt_event_eventtype_id(e);
d052ffc3 1158 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
9d239bd9 1159 // g_assert(lttv_trace_hook_get_first((LttvTraceHook *)hook_data)->f1 != NULL);
1160 g_assert(thf->f1 != NULL);
1161 // g_assert(thf == lttv_trace_hook_get_first((LttvTraceHook *)hook_data));
eed2ef37 1162 LttField *f = thf->f1;
dc877563 1163
b445142a 1164 LttvExecutionSubmode submode;
1165
1166 submode = ((LttvTraceState *)(s->parent.t_context))->irq_names[
eed2ef37 1167 ltt_event_get_unsigned(e, f)];
b445142a 1168
dc877563 1169 /* Do something with the info about being in user or system mode when int? */
b445142a 1170 push_state(s, LTTV_STATE_IRQ, submode);
dc877563 1171 return FALSE;
1172}
1173
1174
b445142a 1175static gboolean irq_exit(void *hook_data, void *call_data)
dc877563 1176{
ba576a78 1177 LttvTracefileState *s = (LttvTracefileState *)call_data;
dc877563 1178
ffd54a90 1179 pop_state(s, LTTV_STATE_IRQ);
dc877563 1180 return FALSE;
1181}
1182
1183
b445142a 1184static gboolean schedchange(void *hook_data, void *call_data)
dc877563 1185{
ba576a78 1186 LttvTracefileState *s = (LttvTracefileState *)call_data;
348c6ba8 1187 guint cpu = ltt_tracefile_num(s->parent.tf);
1188 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
1189 LttvProcessState *process = ts->running_process[cpu];
1190
eed2ef37 1191 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
d052ffc3 1192 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
73394fd3 1193 guint pid_in, pid_out;
1194 gint state_out;
dc877563 1195
eed2ef37 1196 pid_out = ltt_event_get_unsigned(e, thf->f1);
1197 pid_in = ltt_event_get_unsigned(e, thf->f2);
73394fd3 1198 state_out = ltt_event_get_int(e, thf->f3);
348c6ba8 1199
1200 if(likely(process != NULL)) {
b445142a 1201
f95bc830 1202 /* We could not know but it was not the idle process executing.
1203 This should only happen at the beginning, before the first schedule
1204 event, and when the initial information (current process for each CPU)
1205 is missing. It is not obvious how we could, after the fact, compensate
1206 the wrongly attributed statistics. */
1207
240f1fea 1208 //This test only makes sense once the state is known and if there is no
1209 //missing events.
348c6ba8 1210 //if(unlikely(process->pid != pid_out)) {
1211 // g_assert(process->pid == 0);
240f1fea 1212 //}
f95bc830 1213
348c6ba8 1214 if(unlikely(process->state->s == LTTV_STATE_EXIT)) {
1215 process->state->s = LTTV_STATE_ZOMBIE;
791dffa6 1216 process->state->change = s->parent.timestamp;
dbd243b1 1217 } else {
348c6ba8 1218 if(unlikely(state_out == 0)) process->state->s = LTTV_STATE_WAIT_CPU;
1219 else process->state->s = LTTV_STATE_WAIT;
791dffa6 1220 process->state->change = s->parent.timestamp;
1221 }
1222
1223 if(state_out == 32)
1224 exit_process(s, process); /* EXIT_DEAD */
1225 /* see sched.h for states */
dc877563 1226 }
348c6ba8 1227 process = ts->running_process[cpu] =
1228 lttv_state_find_process_or_create(
1229 (LttvTraceState*)s->parent.t_context,
1230 cpu, pid_in,
1231 &s->parent.timestamp);
1232 process->state->s = LTTV_STATE_RUN;
1233 process->cpu = cpu;
1234 // process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)s)->tf);
1235 process->state->change = s->parent.timestamp;
dc877563 1236 return FALSE;
1237}
1238
eed2ef37 1239static gboolean process_fork(void *hook_data, void *call_data)
dc877563 1240{
eed2ef37 1241 LttvTracefileState *s = (LttvTracefileState *)call_data;
1242 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
d052ffc3 1243 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
2cdc690b 1244 LttField *f;
eed2ef37 1245 guint parent_pid;
2cdc690b 1246 guint child_pid;
4ad73431 1247 LttvProcessState *zombie_process;
348c6ba8 1248 guint cpu = ltt_tracefile_num(s->parent.tf);
1249 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
1250 LttvProcessState *process = ts->running_process[cpu];
26275aa2 1251 LttvProcessState *child_process;
2cdc690b 1252
eed2ef37 1253 /* Parent PID */
1254 f = thf->f1;
1255 parent_pid = ltt_event_get_unsigned(e, f);
1256
2cdc690b 1257 /* Child PID */
eed2ef37 1258 f = thf->f2;
1259 child_pid = ltt_event_get_unsigned(e, f);
2cdc690b 1260
15b3d537 1261 /* Mathieu : it seems like the process might have been scheduled in before the
1262 * fork, and, in a rare case, might be the current process. This might happen
d4942a23 1263 * in a SMP case where we don't have enough precision on the clocks.
1264 *
1265 * Test reenabled after precision fixes on time. (Mathieu) */
791dffa6 1266#if 0
348c6ba8 1267 zombie_process = lttv_state_find_process(ts, ANY_CPU, child_pid);
dc877563 1268
1d1df11d 1269 if(unlikely(zombie_process != NULL)) {
4ad73431 1270 /* Reutilisation of PID. Only now we are sure that the old PID
eed2ef37 1271 * has been released. FIXME : should know when release_task happens instead.
4ad73431 1272 */
15b3d537 1273 guint num_cpus = ltt_trace_get_num_cpu(ts->parent.t);
1274 guint i;
1275 for(i=0; i< num_cpus; i++) {
5ac05980 1276 g_assert(zombie_process != ts->running_process[i]);
15b3d537 1277 }
1278
4ad73431 1279 exit_process(s, zombie_process);
1280 }
791dffa6 1281#endif //0
348c6ba8 1282 g_assert(process->pid != child_pid);
eed2ef37 1283 // FIXME : Add this test in the "known state" section
348c6ba8 1284 // g_assert(process->pid == parent_pid);
26275aa2 1285 child_process = lttv_state_find_process(ts, ANY_CPU, child_pid);
1286 if(child_process == NULL) {
1287 lttv_state_create_process(ts, process, cpu,
1288 child_pid, &s->parent.timestamp);
1289 } else {
1290 /* The process has already been created : due to time imprecision between
791dffa6 1291 * multiple CPUs : it has been scheduled in before creation. Note that we
1292 * shouldn't have this kind of imprecision.
26275aa2 1293 *
1294 * Simply put a correct parent.
1295 */
791dffa6 1296 g_assert(0); /* This is a problematic case : the process has been created
1297 before the fork event */
26275aa2 1298 child_process->ppid = process->pid;
1299 }
4ad73431 1300
dc877563 1301 return FALSE;
1302}
1303
1304
eed2ef37 1305static gboolean process_exit(void *hook_data, void *call_data)
dc877563 1306{
eed2ef37 1307 LttvTracefileState *s = (LttvTracefileState *)call_data;
1308 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
d052ffc3 1309 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
eed2ef37 1310 LttField *f;
1311 guint pid;
348c6ba8 1312 guint cpu = ltt_tracefile_num(s->parent.tf);
1313 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
1314 LttvProcessState *process = ts->running_process[cpu];
eed2ef37 1315
1316 pid = ltt_event_get_unsigned(e, thf->f1);
1317
1318 // FIXME : Add this test in the "known state" section
348c6ba8 1319 // g_assert(process->pid == pid);
eed2ef37 1320
348c6ba8 1321 if(likely(process != NULL)) {
1322 process->state->s = LTTV_STATE_EXIT;
2cdc690b 1323 }
1324 return FALSE;
2cdc690b 1325}
1326
eed2ef37 1327static gboolean process_free(void *hook_data, void *call_data)
2da61677 1328{
eed2ef37 1329 LttvTracefileState *s = (LttvTracefileState *)call_data;
348c6ba8 1330 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
eed2ef37 1331 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
d052ffc3 1332 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
2da61677 1333 guint release_pid;
1334 LttvProcessState *process;
1335
1336 /* PID of the process to release */
eed2ef37 1337 release_pid = ltt_event_get_unsigned(e, thf->f1);
15b3d537 1338
1339 g_assert(release_pid != 0);
2da61677 1340
348c6ba8 1341 process = lttv_state_find_process(ts, ANY_CPU, release_pid);
2da61677 1342
1343 if(likely(process != NULL)) {
1344 /* release_task is happening at kernel level : we can now safely release
1345 * the data structure of the process */
5562ddce 1346 //This test is fun, though, as it may happen that
1347 //at time t : CPU 0 : process_free
1348 //at time t+150ns : CPU 1 : schedule out
1349 //Clearly due to time imprecision, we disable it. (Mathieu)
1350 //If this weird case happen, we have no choice but to put the
1351 //Currently running process on the cpu to 0.
791dffa6 1352 //I re-enable it following time precision fixes. (Mathieu)
1353 //Well, in the case where an process is freed by a process on another CPU
1354 //and still scheduled, it happens that this is the schedchange that will
1355 //drop the last reference count. Do not free it here!
0bd2f89c 1356 guint num_cpus = ltt_trace_get_num_cpu(ts->parent.t);
1357 guint i;
1358 for(i=0; i< num_cpus; i++) {
5562ddce 1359 //g_assert(process != ts->running_process[i]);
1360 if(process == ts->running_process[i]) {
791dffa6 1361 //ts->running_process[i] = lttv_state_find_process(ts, i, 0);
1362 break;
5562ddce 1363 }
0bd2f89c 1364 }
791dffa6 1365 if(i == num_cpus) /* process is not scheduled */
1366 exit_process(s, process);
2da61677 1367 }
1368
1369 return FALSE;
1370}
1371
f4b88a7d 1372
1373static gboolean process_exec(void *hook_data, void *call_data)
1374{
1375 LttvTracefileState *s = (LttvTracefileState *)call_data;
1376 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
1377 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
1378 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
743e50fd 1379 //gchar *name;
f4b88a7d 1380 guint cpu = ltt_tracefile_num(s->parent.tf);
1381 LttvProcessState *process = ts->running_process[cpu];
1382
1383 /* PID of the process to release */
743e50fd 1384 guint64 name_len = ltt_event_field_element_number(e, thf->f1);
1385 //name = ltt_event_get_string(e, thf->f1);
f2923fb2 1386 LttField *child = ltt_event_field_element_select(e, thf->f1, 0);
1387 gchar *name_begin =
1388 (gchar*)(ltt_event_data(e)+ltt_event_field_offset(e, child));
743e50fd 1389 gchar *null_term_name = g_new(gchar, name_len+1);
1390 memcpy(null_term_name, name_begin, name_len);
1391 null_term_name[name_len] = '\0';
1392
1393 process->name = g_quark_from_string(null_term_name);
f2923fb2 1394 g_free(null_term_name);
f4b88a7d 1395 return FALSE;
1396}
1397
1398
1399
1400
58c88a41 1401gint lttv_state_hook_add_event_hooks(void *hook_data, void *call_data)
1402{
1403 LttvTracesetState *tss = (LttvTracesetState*)(call_data);
1404
1405 lttv_state_add_event_hooks(tss);
1406
1407 return 0;
1408}
dc877563 1409
308711e5 1410void lttv_state_add_event_hooks(LttvTracesetState *self)
dc877563 1411{
ba576a78 1412 LttvTraceset *traceset = self->parent.ts;
dc877563 1413
eed2ef37 1414 guint i, j, k, l, nb_trace, nb_tracefile;
dc877563 1415
ba576a78 1416 LttvTraceState *ts;
dc877563 1417
ba576a78 1418 LttvTracefileState *tfs;
dc877563 1419
dc877563 1420 GArray *hooks;
1421
eed2ef37 1422 LttvTraceHookByFacility *thf;
1423
1424 LttvTraceHook *hook;
dc877563 1425
1426 LttvAttributeValue val;
1427
9d239bd9 1428 gint ret;
1429
ba576a78 1430 nb_trace = lttv_traceset_number(traceset);
dc877563 1431 for(i = 0 ; i < nb_trace ; i++) {
ba576a78 1432 ts = (LttvTraceState *)self->parent.traces[i];
dc877563 1433
1434 /* Find the eventtype id for the following events and register the
1435 associated by id hooks. */
1436
f4b88a7d 1437 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 11);
1438 hooks = g_array_set_size(hooks, 11);
b445142a 1439
9d239bd9 1440 ret = lttv_trace_find_hook(ts->parent.t,
7b143580 1441 LTT_FACILITY_ASM_I386_KERNEL, LTT_EVENT_SYSCALL_ENTRY,
eed2ef37 1442 LTT_FIELD_SYSCALL_ID, 0, 0,
2c82c4dc 1443 syscall_entry, NULL, &g_array_index(hooks, LttvTraceHook, 0));
9d239bd9 1444 g_assert(!ret);
cbe7c836 1445
9d239bd9 1446 ret = lttv_trace_find_hook(ts->parent.t,
7b143580 1447 LTT_FACILITY_ASM_I386_KERNEL, LTT_EVENT_SYSCALL_EXIT,
eed2ef37 1448 0, 0, 0,
2c82c4dc 1449 syscall_exit, NULL, &g_array_index(hooks, LttvTraceHook, 1));
9d239bd9 1450 g_assert(!ret);
cbe7c836 1451
9d239bd9 1452 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 1453 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY,
1454 LTT_FIELD_TRAP_ID, 0, 0,
2c82c4dc 1455 trap_entry, NULL, &g_array_index(hooks, LttvTraceHook, 2));
9d239bd9 1456 g_assert(!ret);
cbe7c836 1457
9d239bd9 1458 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 1459 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT,
1460 0, 0, 0,
2c82c4dc 1461 trap_exit, NULL, &g_array_index(hooks, LttvTraceHook, 3));
9d239bd9 1462 g_assert(!ret);
cbe7c836 1463
9d239bd9 1464 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 1465 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
1466 LTT_FIELD_IRQ_ID, 0, 0,
2c82c4dc 1467 irq_entry, NULL, &g_array_index(hooks, LttvTraceHook, 4));
9d239bd9 1468 g_assert(!ret);
cbe7c836 1469
9d239bd9 1470 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 1471 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
1472 0, 0, 0,
2c82c4dc 1473 irq_exit, NULL, &g_array_index(hooks, LttvTraceHook, 5));
9d239bd9 1474 g_assert(!ret);
cbe7c836 1475
9d239bd9 1476 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 1477 LTT_FACILITY_PROCESS, LTT_EVENT_SCHEDCHANGE,
1478 LTT_FIELD_OUT, LTT_FIELD_IN, LTT_FIELD_OUT_STATE,
2c82c4dc 1479 schedchange, NULL, &g_array_index(hooks, LttvTraceHook, 6));
9d239bd9 1480 g_assert(!ret);
cbe7c836 1481
9d239bd9 1482 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 1483 LTT_FACILITY_PROCESS, LTT_EVENT_FORK,
1484 LTT_FIELD_PARENT_PID, LTT_FIELD_CHILD_PID, 0,
2c82c4dc 1485 process_fork, NULL, &g_array_index(hooks, LttvTraceHook, 7));
9d239bd9 1486 g_assert(!ret);
eed2ef37 1487
9d239bd9 1488 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 1489 LTT_FACILITY_PROCESS, LTT_EVENT_EXIT,
1490 LTT_FIELD_PID, 0, 0,
2c82c4dc 1491 process_exit, NULL, &g_array_index(hooks, LttvTraceHook, 8));
9d239bd9 1492 g_assert(!ret);
eed2ef37 1493
9d239bd9 1494 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 1495 LTT_FACILITY_PROCESS, LTT_EVENT_FREE,
1496 LTT_FIELD_PID, 0, 0,
2c82c4dc 1497 process_free, NULL, &g_array_index(hooks, LttvTraceHook, 9));
9d239bd9 1498 g_assert(!ret);
2cdc690b 1499
f4b88a7d 1500 ret = lttv_trace_find_hook(ts->parent.t,
1501 LTT_FACILITY_FS, LTT_EVENT_EXEC,
1502 LTT_FIELD_FILENAME, 0, 0,
1503 process_exec, NULL, &g_array_index(hooks, LttvTraceHook, 10));
1504 g_assert(!ret);
1505
1506
cbe7c836 1507
a5ba1787 1508 /* Add these hooks to each event_by_id hooks list */
dc877563 1509
eed2ef37 1510 nb_tracefile = ts->parent.tracefiles->len;
dbb7bb09 1511
dc877563 1512 for(j = 0 ; j < nb_tracefile ; j++) {
eed2ef37 1513 tfs =
9d239bd9 1514 LTTV_TRACEFILE_STATE(g_array_index(ts->parent.tracefiles,
1515 LttvTracefileContext*, j));
dc877563 1516
1517 for(k = 0 ; k < hooks->len ; k++) {
eed2ef37 1518 hook = &g_array_index(hooks, LttvTraceHook, k);
1519 for(l=0;l<hook->fac_list->len;l++) {
1520 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1521 lttv_hooks_add(
1522 lttv_hooks_by_id_find(tfs->parent.event_by_id, thf->id),
1523 thf->h,
d052ffc3 1524 thf,
eed2ef37 1525 LTTV_PRIO_STATE);
1526 }
ffd54a90 1527 }
dc877563 1528 }
ba576a78 1529 lttv_attribute_find(self->parent.a, LTTV_STATE_HOOKS, LTTV_POINTER, &val);
1530 *(val.v_pointer) = hooks;
dc877563 1531 }
1532}
1533
58c88a41 1534gint lttv_state_hook_remove_event_hooks(void *hook_data, void *call_data)
1535{
1536 LttvTracesetState *tss = (LttvTracesetState*)(call_data);
1537
1538 lttv_state_remove_event_hooks(tss);
1539
1540 return 0;
1541}
dc877563 1542
308711e5 1543void lttv_state_remove_event_hooks(LttvTracesetState *self)
dc877563 1544{
ba576a78 1545 LttvTraceset *traceset = self->parent.ts;
dc877563 1546
eed2ef37 1547 guint i, j, k, l, nb_trace, nb_tracefile;
dc877563 1548
ba576a78 1549 LttvTraceState *ts;
dc877563 1550
ba576a78 1551 LttvTracefileState *tfs;
dc877563 1552
dc877563 1553 GArray *hooks;
1554
eed2ef37 1555 LttvTraceHook *hook;
1556
1557 LttvTraceHookByFacility *thf;
dc877563 1558
1559 LttvAttributeValue val;
1560
ba576a78 1561 nb_trace = lttv_traceset_number(traceset);
dc877563 1562 for(i = 0 ; i < nb_trace ; i++) {
021eeb41 1563 ts = LTTV_TRACE_STATE(self->parent.traces[i]);
ba576a78 1564 lttv_attribute_find(self->parent.a, LTTV_STATE_HOOKS, LTTV_POINTER, &val);
1565 hooks = *(val.v_pointer);
dc877563 1566
a5ba1787 1567 /* Remove these hooks from each event_by_id hooks list */
dc877563 1568
eed2ef37 1569 nb_tracefile = ts->parent.tracefiles->len;
dbb7bb09 1570
dc877563 1571 for(j = 0 ; j < nb_tracefile ; j++) {
eed2ef37 1572 tfs =
cb03932a 1573 LTTV_TRACEFILE_STATE(g_array_index(ts->parent.tracefiles,
1574 LttvTracefileContext*, j));
dc877563 1575
1576 for(k = 0 ; k < hooks->len ; k++) {
eed2ef37 1577 hook = &g_array_index(hooks, LttvTraceHook, k);
1578 for(l=0;l<hook->fac_list->len;l++) {
1579 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1580
1581 lttv_hooks_remove_data(
1582 lttv_hooks_by_id_find(tfs->parent.event_by_id, thf->id),
1583 thf->h,
d052ffc3 1584 thf);
eed2ef37 1585 }
ffd54a90 1586 }
dc877563 1587 }
1986f254 1588 for(k = 0 ; k < hooks->len ; k++)
1589 lttv_trace_hook_destroy(&g_array_index(hooks, LttvTraceHook, k));
dc877563 1590 g_array_free(hooks, TRUE);
1591 }
1592}
1593
eed2ef37 1594static gboolean state_save_event_hook(void *hook_data, void *call_data)
1595{
1596 guint *event_count = (guint*)hook_data;
1597
1598 /* Only save at LTTV_STATE_SAVE_INTERVAL */
1599 if(likely((*event_count)++ < LTTV_STATE_SAVE_INTERVAL))
1600 return FALSE;
1601 else
18c87975 1602 *event_count = 0;
eed2ef37 1603
1604 LttvTracefileState *self = (LttvTracefileState *)call_data;
1605
1606 LttvTracefileState *tfcs;
1607
1608 LttvTraceState *tcs = (LttvTraceState *)(self->parent.t_context);
1609
1610 LttEventPosition *ep;
1611
1612 guint i;
1613
1614 LttTracefile *tf;
1615
1616 LttvAttribute *saved_states_tree, *saved_state_tree;
1617
1618 LttvAttributeValue value;
1619
1620 saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a,
1621 LTTV_STATE_SAVED_STATES);
1622 saved_state_tree = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
1623 value = lttv_attribute_add(saved_states_tree,
1624 lttv_attribute_get_number(saved_states_tree), LTTV_GOBJECT);
1625 *(value.v_gobject) = (GObject *)saved_state_tree;
1626 value = lttv_attribute_add(saved_state_tree, LTTV_STATE_TIME, LTTV_TIME);
1627 *(value.v_time) = self->parent.timestamp;
1628 lttv_state_save(tcs, saved_state_tree);
1629 g_debug("Saving state at time %lu.%lu", self->parent.timestamp.tv_sec,
1630 self->parent.timestamp.tv_nsec);
1631
1632 *(tcs->max_time_state_recomputed_in_seek) = self->parent.timestamp;
1633
1634 return FALSE;
1635}
1636
14aecf75 1637static gboolean state_save_after_trace_hook(void *hook_data, void *call_data)
1638{
1639 LttvTraceState *tcs = (LttvTraceState *)(call_data);
1640
1641 *(tcs->max_time_state_recomputed_in_seek) = tcs->parent.time_span.end_time;
1642
1643 return FALSE;
1644}
1645
eed2ef37 1646#if 0
08b1c66e 1647static gboolean block_start(void *hook_data, void *call_data)
308711e5 1648{
dbb7bb09 1649 LttvTracefileState *self = (LttvTracefileState *)call_data;
308711e5 1650
dbb7bb09 1651 LttvTracefileState *tfcs;
308711e5 1652
dbb7bb09 1653 LttvTraceState *tcs = (LttvTraceState *)(self->parent.t_context);
1654
1655 LttEventPosition *ep;
308711e5 1656
dbb7bb09 1657 guint i, nb_block, nb_event, nb_tracefile;
308711e5 1658
1659 LttTracefile *tf;
1660
1661 LttvAttribute *saved_states_tree, *saved_state_tree;
1662
1663 LttvAttributeValue value;
1664
dbb7bb09 1665 ep = ltt_event_position_new();
eed2ef37 1666
1667 nb_tracefile = tcs->parent.tracefiles->len;
dbb7bb09 1668
1669 /* Count the number of events added since the last block end in any
1670 tracefile. */
1671
1672 for(i = 0 ; i < nb_tracefile ; i++) {
eed2ef37 1673 tfcs =
1674 LTTV_TRACEFILE_STATE(&g_array_index(tcs->parent.tracefiles,
1675 LttvTracefileContext, i));
dbb7bb09 1676 ltt_event_position(tfcs->parent.e, ep);
1677 ltt_event_position_get(ep, &nb_block, &nb_event, &tf);
1678 tcs->nb_event += nb_event - tfcs->saved_position;
1679 tfcs->saved_position = nb_event;
1680 }
1681 g_free(ep);
308711e5 1682
308711e5 1683 if(tcs->nb_event >= tcs->save_interval) {
1684 saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a,
1685 LTTV_STATE_SAVED_STATES);
1686 saved_state_tree = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
1687 value = lttv_attribute_add(saved_states_tree,
1688 lttv_attribute_get_number(saved_states_tree), LTTV_GOBJECT);
1689 *(value.v_gobject) = (GObject *)saved_state_tree;
1690 value = lttv_attribute_add(saved_state_tree, LTTV_STATE_TIME, LTTV_TIME);
dbb7bb09 1691 *(value.v_time) = self->parent.timestamp;
308711e5 1692 lttv_state_save(tcs, saved_state_tree);
1693 tcs->nb_event = 0;
08b1c66e 1694 g_debug("Saving state at time %lu.%lu", self->parent.timestamp.tv_sec,
1695 self->parent.timestamp.tv_nsec);
308711e5 1696 }
dbb7bb09 1697 *(tcs->max_time_state_recomputed_in_seek) = self->parent.timestamp;
308711e5 1698 return FALSE;
1699}
eed2ef37 1700#endif //0
308711e5 1701
eed2ef37 1702#if 0
08b1c66e 1703static gboolean block_end(void *hook_data, void *call_data)
1704{
1705 LttvTracefileState *self = (LttvTracefileState *)call_data;
1706
1707 LttvTraceState *tcs = (LttvTraceState *)(self->parent.t_context);
1708
1709 LttTracefile *tf;
1710
1711 LttEventPosition *ep;
1712
1713 guint nb_block, nb_event;
1714
1715 ep = ltt_event_position_new();
1716 ltt_event_position(self->parent.e, ep);
1717 ltt_event_position_get(ep, &nb_block, &nb_event, &tf);
1718 tcs->nb_event += nb_event - self->saved_position + 1;
1719 self->saved_position = 0;
1720 *(tcs->max_time_state_recomputed_in_seek) = self->parent.timestamp;
1721 g_free(ep);
00e74b69 1722
1723 return FALSE;
08b1c66e 1724}
eed2ef37 1725#endif //0
1726#if 0
308711e5 1727void lttv_state_save_add_event_hooks(LttvTracesetState *self)
1728{
1729 LttvTraceset *traceset = self->parent.ts;
1730
00e74b69 1731 guint i, j, nb_trace, nb_tracefile;
308711e5 1732
1733 LttvTraceState *ts;
1734
1735 LttvTracefileState *tfs;
1736
08b1c66e 1737 LttvTraceHook hook_start, hook_end;
308711e5 1738
1739 nb_trace = lttv_traceset_number(traceset);
1740 for(i = 0 ; i < nb_trace ; i++) {
1741 ts = (LttvTraceState *)self->parent.traces[i];
eed2ef37 1742
08b1c66e 1743 lttv_trace_find_hook(ts->parent.t, "core","block_start",NULL,
1744 NULL, NULL, block_start, &hook_start);
308711e5 1745 lttv_trace_find_hook(ts->parent.t, "core","block_end",NULL,
08b1c66e 1746 NULL, NULL, block_end, &hook_end);
308711e5 1747
eed2ef37 1748 nb_tracefile = ts->parent.tracefiles->len;
308711e5 1749
dbb7bb09 1750 for(j = 0 ; j < nb_tracefile ; j++) {
eed2ef37 1751 tfs =
1752 LTTV_TRACEFILE_STATE(&g_array_index(ts->parent.tracefiles,
1753 LttvTracefileContext, j));
a5ba1787 1754 lttv_hooks_add(lttv_hooks_by_id_find(tfs->parent.event_by_id,
eed2ef37 1755 hook_start.id), hook_start.h, NULL, LTTV_PRIO_STATE);
a5ba1787 1756 lttv_hooks_add(lttv_hooks_by_id_find(tfs->parent.event_by_id,
eed2ef37 1757 hook_end.id), hook_end.h, NULL, LTTV_PRIO_STATE);
1758 }
1759 }
1760}
1761#endif //0
1762
1763void lttv_state_save_add_event_hooks(LttvTracesetState *self)
1764{
1765 LttvTraceset *traceset = self->parent.ts;
1766
1767 guint i, j, nb_trace, nb_tracefile;
1768
1769 LttvTraceState *ts;
1770
1771 LttvTracefileState *tfs;
1772
1773
1774 nb_trace = lttv_traceset_number(traceset);
1775 for(i = 0 ; i < nb_trace ; i++) {
1776
1777 ts = (LttvTraceState *)self->parent.traces[i];
1778 nb_tracefile = ts->parent.tracefiles->len;
1779
3054461a 1780 guint *event_count = g_new(guint, 1);
1781 *event_count = 0;
1782
eed2ef37 1783 for(j = 0 ; j < nb_tracefile ; j++) {
1784 tfs =
cb03932a 1785 LTTV_TRACEFILE_STATE(g_array_index(ts->parent.tracefiles,
1786 LttvTracefileContext*, j));
eed2ef37 1787 lttv_hooks_add(tfs->parent.event,
1788 state_save_event_hook,
1789 event_count,
1790 LTTV_PRIO_STATE);
1791
308711e5 1792 }
1793 }
14aecf75 1794
1795 lttv_process_traceset_begin(&self->parent,
1796 NULL, NULL, NULL, NULL, NULL);
1797
308711e5 1798}
1799
b56b5fec 1800gint lttv_state_save_hook_add_event_hooks(void *hook_data, void *call_data)
1801{
1802 LttvTracesetState *tss = (LttvTracesetState*)(call_data);
1803
1804 lttv_state_save_add_event_hooks(tss);
1805
1806 return 0;
1807}
1808
308711e5 1809
eed2ef37 1810#if 0
308711e5 1811void lttv_state_save_remove_event_hooks(LttvTracesetState *self)
1812{
1813 LttvTraceset *traceset = self->parent.ts;
1814
00e74b69 1815 guint i, j, nb_trace, nb_tracefile;
308711e5 1816
1817 LttvTraceState *ts;
1818
1819 LttvTracefileState *tfs;
1820
08b1c66e 1821 LttvTraceHook hook_start, hook_end;
308711e5 1822
1823 nb_trace = lttv_traceset_number(traceset);
1824 for(i = 0 ; i < nb_trace ; i++) {
1825 ts = LTTV_TRACE_STATE(self->parent.traces[i]);
eed2ef37 1826
08b1c66e 1827 lttv_trace_find_hook(ts->parent.t, "core","block_start",NULL,
1828 NULL, NULL, block_start, &hook_start);
1829
308711e5 1830 lttv_trace_find_hook(ts->parent.t, "core","block_end",NULL,
08b1c66e 1831 NULL, NULL, block_end, &hook_end);
308711e5 1832
eed2ef37 1833 nb_tracefile = ts->parent.tracefiles->len;
308711e5 1834
dbb7bb09 1835 for(j = 0 ; j < nb_tracefile ; j++) {
eed2ef37 1836 tfs =
1837 LTTV_TRACEFILE_STATE(&g_array_index(ts->parent.tracefiles,
1838 LttvTracefileContext, j));
308711e5 1839 lttv_hooks_remove_data(lttv_hooks_by_id_find(
a5ba1787 1840 tfs->parent.event_by_id, hook_start.id), hook_start.h, NULL);
08b1c66e 1841 lttv_hooks_remove_data(lttv_hooks_by_id_find(
a5ba1787 1842 tfs->parent.event_by_id, hook_end.id), hook_end.h, NULL);
308711e5 1843 }
1844 }
1845}
eed2ef37 1846#endif //0
1847
1848void lttv_state_save_remove_event_hooks(LttvTracesetState *self)
1849{
1850 LttvTraceset *traceset = self->parent.ts;
1851
1852 guint i, j, nb_trace, nb_tracefile;
1853
1854 LttvTraceState *ts;
1855
1856 LttvTracefileState *tfs;
1857
14aecf75 1858 LttvHooks *after_trace = lttv_hooks_new();
1859
1860 lttv_hooks_add(after_trace,
1861 state_save_after_trace_hook,
1862 NULL,
1863 LTTV_PRIO_STATE);
1864
1865
1866 lttv_process_traceset_end(&self->parent,
1867 NULL, after_trace, NULL, NULL, NULL);
eed2ef37 1868
14aecf75 1869 lttv_hooks_destroy(after_trace);
1870
eed2ef37 1871 nb_trace = lttv_traceset_number(traceset);
1872 for(i = 0 ; i < nb_trace ; i++) {
1873
1874 ts = (LttvTraceState *)self->parent.traces[i];
1875 nb_tracefile = ts->parent.tracefiles->len;
1876
22b165e9 1877 guint *event_count = NULL;
eed2ef37 1878
1879 for(j = 0 ; j < nb_tracefile ; j++) {
1880 tfs =
cb03932a 1881 LTTV_TRACEFILE_STATE(g_array_index(ts->parent.tracefiles,
1882 LttvTracefileContext*, j));
eed2ef37 1883 event_count = lttv_hooks_remove(tfs->parent.event,
1884 state_save_event_hook);
eed2ef37 1885 }
22b165e9 1886 if(event_count) g_free(event_count);
eed2ef37 1887 }
1888}
308711e5 1889
b56b5fec 1890gint lttv_state_save_hook_remove_event_hooks(void *hook_data, void *call_data)
1891{
1892 LttvTracesetState *tss = (LttvTracesetState*)(call_data);
1893
1894 lttv_state_save_remove_event_hooks(tss);
1895
1896 return 0;
1897}
308711e5 1898
dd025f91 1899void lttv_state_traceset_seek_time_closest(LttvTracesetState *self, LttTime t)
308711e5 1900{
1901 LttvTraceset *traceset = self->parent.ts;
1902
00e74b69 1903 guint i, nb_trace;
308711e5 1904
1905 int min_pos, mid_pos, max_pos;
1906
728d0c3e 1907 guint call_rest = 0;
1908
308711e5 1909 LttvTraceState *tcs;
1910
1911 LttvAttributeValue value;
1912
1913 LttvAttributeType type;
1914
1915 LttvAttributeName name;
1916
1917 LttvAttribute *saved_states_tree, *saved_state_tree, *closest_tree;
1918
d448fce2 1919 //g_tree_destroy(self->parent.pqueue);
1920 //self->parent.pqueue = g_tree_new(compare_tracefile);
348c6ba8 1921
728d0c3e 1922 g_info("Entering seek_time_closest for time %lu.%lu", t.tv_sec, t.tv_nsec);
1923
308711e5 1924 nb_trace = lttv_traceset_number(traceset);
1925 for(i = 0 ; i < nb_trace ; i++) {
1926 tcs = (LttvTraceState *)self->parent.traces[i];
1927
2a2fa4f0 1928 if(ltt_time_compare(t, *(tcs->max_time_state_recomputed_in_seek)) < 0) {
1929 saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a,
1930 LTTV_STATE_SAVED_STATES);
1931 min_pos = -1;
1932
1933 if(saved_states_tree) {
dd025f91 1934 max_pos = lttv_attribute_get_number(saved_states_tree) - 1;
1935 mid_pos = max_pos / 2;
1936 while(min_pos < max_pos) {
1937 type = lttv_attribute_get(saved_states_tree, mid_pos, &name, &value);
1938 g_assert(type == LTTV_GOBJECT);
1939 saved_state_tree = *((LttvAttribute **)(value.v_gobject));
1940 type = lttv_attribute_get_by_name(saved_state_tree, LTTV_STATE_TIME,
1941 &value);
1942 g_assert(type == LTTV_TIME);
1943 if(ltt_time_compare(*(value.v_time), t) < 0) {
1944 min_pos = mid_pos;
1945 closest_tree = saved_state_tree;
1946 }
1947 else max_pos = mid_pos - 1;
1948
1949 mid_pos = (min_pos + max_pos + 1) / 2;
1950 }
2a2fa4f0 1951 }
dd025f91 1952
2a2fa4f0 1953 /* restore the closest earlier saved state */
f95bc830 1954 if(min_pos != -1) {
1955 lttv_state_restore(tcs, closest_tree);
728d0c3e 1956 call_rest = 1;
f95bc830 1957 }
dd025f91 1958
2a2fa4f0 1959 /* There is no saved state, yet we want to have it. Restart at T0 */
dd025f91 1960 else {
1961 restore_init_state(tcs);
1962 lttv_process_trace_seek_time(&(tcs->parent), ltt_time_zero);
308711e5 1963 }
9444deae 1964 }
dd025f91 1965 /* We want to seek quickly without restoring/updating the state */
1966 else {
308711e5 1967 restore_init_state(tcs);
dd025f91 1968 lttv_process_trace_seek_time(&(tcs->parent), t);
308711e5 1969 }
308711e5 1970 }
728d0c3e 1971 if(!call_rest) g_info("NOT Calling restore");
308711e5 1972}
1973
1974
1975static void
1976traceset_state_instance_init (GTypeInstance *instance, gpointer g_class)
1977{
1978}
1979
1980
1981static void
1982traceset_state_finalize (LttvTracesetState *self)
1983{
1984 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))->
1985 finalize(G_OBJECT(self));
1986}
1987
1988
1989static void
1990traceset_state_class_init (LttvTracesetContextClass *klass)
1991{
1992 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
1993
1994 gobject_class->finalize = (void (*)(GObject *self)) traceset_state_finalize;
1995 klass->init = (void (*)(LttvTracesetContext *self, LttvTraceset *ts))init;
1996 klass->fini = (void (*)(LttvTracesetContext *self))fini;
1997 klass->new_traceset_context = new_traceset_context;
1998 klass->new_trace_context = new_trace_context;
1999 klass->new_tracefile_context = new_tracefile_context;
2000}
2001
2002
2003GType
2004lttv_traceset_state_get_type(void)
2005{
2006 static GType type = 0;
2007 if (type == 0) {
2008 static const GTypeInfo info = {
2009 sizeof (LttvTracesetStateClass),
2010 NULL, /* base_init */
2011 NULL, /* base_finalize */
2012 (GClassInitFunc) traceset_state_class_init, /* class_init */
2013 NULL, /* class_finalize */
2014 NULL, /* class_data */
dbb7bb09 2015 sizeof (LttvTracesetState),
308711e5 2016 0, /* n_preallocs */
00e74b69 2017 (GInstanceInitFunc) traceset_state_instance_init, /* instance_init */
2018 NULL /* value handling */
308711e5 2019 };
2020
2021 type = g_type_register_static (LTTV_TRACESET_CONTEXT_TYPE, "LttvTracesetStateType",
2022 &info, 0);
2023 }
2024 return type;
2025}
2026
2027
2028static void
2029trace_state_instance_init (GTypeInstance *instance, gpointer g_class)
2030{
2031}
2032
2033
2034static void
2035trace_state_finalize (LttvTraceState *self)
2036{
2037 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_CONTEXT_TYPE))->
2038 finalize(G_OBJECT(self));
2039}
2040
2041
2042static void
2043trace_state_class_init (LttvTraceStateClass *klass)
2044{
2045 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
2046
2047 gobject_class->finalize = (void (*)(GObject *self)) trace_state_finalize;
2048 klass->state_save = state_save;
2049 klass->state_restore = state_restore;
2050 klass->state_saved_free = state_saved_free;
2051}
2052
2053
2054GType
2055lttv_trace_state_get_type(void)
2056{
2057 static GType type = 0;
2058 if (type == 0) {
2059 static const GTypeInfo info = {
2060 sizeof (LttvTraceStateClass),
2061 NULL, /* base_init */
2062 NULL, /* base_finalize */
2063 (GClassInitFunc) trace_state_class_init, /* class_init */
2064 NULL, /* class_finalize */
2065 NULL, /* class_data */
2066 sizeof (LttvTraceState),
2067 0, /* n_preallocs */
00e74b69 2068 (GInstanceInitFunc) trace_state_instance_init, /* instance_init */
2069 NULL /* value handling */
308711e5 2070 };
2071
2072 type = g_type_register_static (LTTV_TRACE_CONTEXT_TYPE,
2073 "LttvTraceStateType", &info, 0);
2074 }
2075 return type;
2076}
2077
2078
2079static void
2080tracefile_state_instance_init (GTypeInstance *instance, gpointer g_class)
2081{
2082}
2083
2084
2085static void
2086tracefile_state_finalize (LttvTracefileState *self)
2087{
2088 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_CONTEXT_TYPE))->
2089 finalize(G_OBJECT(self));
2090}
2091
2092
2093static void
2094tracefile_state_class_init (LttvTracefileStateClass *klass)
2095{
2096 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
2097
2098 gobject_class->finalize = (void (*)(GObject *self)) tracefile_state_finalize;
2099}
2100
2101
2102GType
2103lttv_tracefile_state_get_type(void)
2104{
2105 static GType type = 0;
2106 if (type == 0) {
2107 static const GTypeInfo info = {
2108 sizeof (LttvTracefileStateClass),
2109 NULL, /* base_init */
2110 NULL, /* base_finalize */
2111 (GClassInitFunc) tracefile_state_class_init, /* class_init */
2112 NULL, /* class_finalize */
2113 NULL, /* class_data */
2114 sizeof (LttvTracefileState),
2115 0, /* n_preallocs */
00e74b69 2116 (GInstanceInitFunc) tracefile_state_instance_init, /* instance_init */
2117 NULL /* value handling */
308711e5 2118 };
2119
2120 type = g_type_register_static (LTTV_TRACEFILE_CONTEXT_TYPE,
2121 "LttvTracefileStateType", &info, 0);
2122 }
2123 return type;
2124}
2125
2126
08b1c66e 2127static void module_init()
ffd54a90 2128{
2129 LTTV_STATE_UNNAMED = g_quark_from_string("unnamed");
b445142a 2130 LTTV_STATE_MODE_UNKNOWN = g_quark_from_string("unknown execution mode");
ffd54a90 2131 LTTV_STATE_USER_MODE = g_quark_from_string("user mode");
2132 LTTV_STATE_WAIT_FORK = g_quark_from_string("wait fork");
2133 LTTV_STATE_SYSCALL = g_quark_from_string("system call");
2134 LTTV_STATE_TRAP = g_quark_from_string("trap");
2135 LTTV_STATE_IRQ = g_quark_from_string("irq");
b445142a 2136 LTTV_STATE_SUBMODE_UNKNOWN = g_quark_from_string("unknown submode");
2137 LTTV_STATE_SUBMODE_NONE = g_quark_from_string("(no submode)");
ffd54a90 2138 LTTV_STATE_WAIT_CPU = g_quark_from_string("wait for cpu");
dbd243b1 2139 LTTV_STATE_EXIT = g_quark_from_string("exiting");
0828099d 2140 LTTV_STATE_ZOMBIE = g_quark_from_string("zombie");
ffd54a90 2141 LTTV_STATE_WAIT = g_quark_from_string("wait for I/O");
2142 LTTV_STATE_RUN = g_quark_from_string("running");
791dffa6 2143 LTTV_STATE_DEAD = g_quark_from_string("dead");
308711e5 2144 LTTV_STATE_TRACEFILES = g_quark_from_string("tracefiles");
2145 LTTV_STATE_PROCESSES = g_quark_from_string("processes");
2146 LTTV_STATE_PROCESS = g_quark_from_string("process");
348c6ba8 2147 LTTV_STATE_RUNNING_PROCESS = g_quark_from_string("running_process");
308711e5 2148 LTTV_STATE_EVENT = g_quark_from_string("event");
2149 LTTV_STATE_SAVED_STATES = g_quark_from_string("saved states");
dbb7bb09 2150 LTTV_STATE_SAVED_STATES_TIME = g_quark_from_string("saved states time");
308711e5 2151 LTTV_STATE_TIME = g_quark_from_string("time");
ffd54a90 2152 LTTV_STATE_HOOKS = g_quark_from_string("saved state hooks");
f95bc830 2153 LTTV_STATE_NAME_TABLES = g_quark_from_string("name tables");
2154 LTTV_STATE_TRACE_STATE_USE_COUNT =
2155 g_quark_from_string("trace_state_use_count");
eed2ef37 2156
2157
2158 LTT_FACILITY_KERNEL = g_quark_from_string("kernel");
7b143580 2159 LTT_FACILITY_ASM_I386_KERNEL = g_quark_from_string("asm_i386_kernel");
eed2ef37 2160 LTT_FACILITY_PROCESS = g_quark_from_string("process");
f4b88a7d 2161 LTT_FACILITY_FS = g_quark_from_string("fs");
eed2ef37 2162
2163
2164 LTT_EVENT_SYSCALL_ENTRY = g_quark_from_string("syscall_entry");
2165 LTT_EVENT_SYSCALL_EXIT = g_quark_from_string("syscall_exit");
2166 LTT_EVENT_TRAP_ENTRY = g_quark_from_string("trap_entry");
2167 LTT_EVENT_TRAP_EXIT = g_quark_from_string("trap_exit");
2168 LTT_EVENT_IRQ_ENTRY = g_quark_from_string("irq_entry");
2169 LTT_EVENT_IRQ_EXIT = g_quark_from_string("irq_exit");
2170 LTT_EVENT_SCHEDCHANGE = g_quark_from_string("schedchange");
2171 LTT_EVENT_FORK = g_quark_from_string("fork");
2172 LTT_EVENT_EXIT = g_quark_from_string("exit");
2173 LTT_EVENT_FREE = g_quark_from_string("free");
f4b88a7d 2174 LTT_EVENT_EXEC = g_quark_from_string("exec");
eed2ef37 2175
2176
2177 LTT_FIELD_SYSCALL_ID = g_quark_from_string("syscall_id");
2178 LTT_FIELD_TRAP_ID = g_quark_from_string("trap_id");
2179 LTT_FIELD_IRQ_ID = g_quark_from_string("irq_id");
2180 LTT_FIELD_OUT = g_quark_from_string("out");
2181 LTT_FIELD_IN = g_quark_from_string("in");
2182 LTT_FIELD_OUT_STATE = g_quark_from_string("out_state");
2183 LTT_FIELD_PARENT_PID = g_quark_from_string("parent_pid");
2184 LTT_FIELD_CHILD_PID = g_quark_from_string("child_pid");
2185 LTT_FIELD_PID = g_quark_from_string("pid");
f4b88a7d 2186 LTT_FIELD_FILENAME = g_quark_from_string("filename");
eed2ef37 2187
ffd54a90 2188}
dc877563 2189
08b1c66e 2190static void module_destroy()
ffd54a90 2191{
2192}
dc877563 2193
2194
08b1c66e 2195LTTV_MODULE("state", "State computation", \
2196 "Update the system state, possibly saving it at intervals", \
2197 module_init, module_destroy)
2198
dc877563 2199
2200
This page took 0.152784 seconds and 4 git commands to generate.