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