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