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