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