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