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