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