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