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