Add member timestamp and cpuid to LttvTracesetPosition to improve the comparaison...
[lttv.git] / 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
5e29121a 19#define _GNU_SOURCE
4e4d11b3 20#ifdef HAVE_CONFIG_H
21#include <config.h>
22#endif
e865422c 23
c7146c5c 24#include <glib.h>
08b1c66e 25#include <lttv/lttv.h>
26#include <lttv/module.h>
dc877563 27#include <lttv/state.h>
7a4bdb54
YB
28#include <lttv/compiler.h>
29#include <lttv/traceset.h>
88bf15f0 30#include <lttv/trace.h>
f95bc830 31#include <stdio.h>
b3fd4c02 32#include <string.h>
43ed82b5 33#include <inttypes.h>
c73ce169 34#include <babeltrace/babeltrace.h>
dc877563 35
e8f2280c 36#define PREALLOCATED_EXECUTION_STACK 10
37
750eb11a 38/* Channel Quarks */
eed2ef37 39
40GQuark
90e19f82
AM
41 LTT_CHANNEL_FD_STATE,
42 LTT_CHANNEL_GLOBAL_STATE,
43 LTT_CHANNEL_IRQ_STATE,
44 LTT_CHANNEL_MODULE_STATE,
45 LTT_CHANNEL_NETIF_STATE,
46 LTT_CHANNEL_SOFTIRQ_STATE,
47 LTT_CHANNEL_SWAP_STATE,
48 LTT_CHANNEL_SYSCALL_STATE,
49 LTT_CHANNEL_TASK_STATE,
50 LTT_CHANNEL_VM_STATE,
51 LTT_CHANNEL_KPROBE_STATE,
52 LTT_CHANNEL_FS,
53 LTT_CHANNEL_KERNEL,
54 LTT_CHANNEL_MM,
55 LTT_CHANNEL_USERSPACE,
56 LTT_CHANNEL_BLOCK;
eed2ef37 57
58/* Events Quarks */
59
60GQuark
90e19f82
AM
61 LTT_EVENT_SYSCALL_ENTRY,
62 LTT_EVENT_SYSCALL_EXIT,
63 LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY,
64 LTT_EVENT_PAGE_FAULT_NOSEM_EXIT,
65 LTT_EVENT_PAGE_FAULT_ENTRY,
66 LTT_EVENT_PAGE_FAULT_EXIT,
7a4bdb54
YB
67 //LTT_EVENT_TRAP_ENTRY,
68 //LTT_EVENT_TRAP_EXIT,
90e19f82
AM
69 LTT_EVENT_IRQ_ENTRY,
70 LTT_EVENT_IRQ_EXIT,
71 LTT_EVENT_SOFT_IRQ_RAISE,
72 LTT_EVENT_SOFT_IRQ_ENTRY,
73 LTT_EVENT_SOFT_IRQ_EXIT,
74 LTT_EVENT_SCHED_SCHEDULE,
75 LTT_EVENT_SCHED_TRY_WAKEUP,
76 LTT_EVENT_PROCESS_FORK,
77 LTT_EVENT_KTHREAD_CREATE,
78 LTT_EVENT_PROCESS_EXIT,
79 LTT_EVENT_PROCESS_FREE,
80 LTT_EVENT_EXEC,
81 LTT_EVENT_PROCESS_STATE,
82 LTT_EVENT_STATEDUMP_END,
83 LTT_EVENT_FUNCTION_ENTRY,
84 LTT_EVENT_FUNCTION_EXIT,
85 LTT_EVENT_THREAD_BRAND,
86 LTT_EVENT_REQUEST_ISSUE,
87 LTT_EVENT_REQUEST_COMPLETE,
88 LTT_EVENT_LIST_INTERRUPT,
89 LTT_EVENT_SYS_CALL_TABLE,
90 LTT_EVENT_SOFTIRQ_VEC,
91 LTT_EVENT_KPROBE_TABLE,
92 LTT_EVENT_KPROBE,
93 LTT_EVENT_OPEN,
94 LTT_EVENT_READ,
95 LTT_EVENT_POLL_EVENT;
eed2ef37 96
97/* Fields Quarks */
98
99GQuark
90e19f82
AM
100 LTT_FIELD_SYSCALL_ID,
101 LTT_FIELD_TRAP_ID,
102 LTT_FIELD_IRQ_ID,
103 LTT_FIELD_SOFT_IRQ_ID,
104 LTT_FIELD_PREV_PID,
105 LTT_FIELD_NEXT_PID,
106 LTT_FIELD_PREV_STATE,
107 LTT_FIELD_PARENT_PID,
108 LTT_FIELD_CHILD_PID,
109 LTT_FIELD_PID,
110 LTT_FIELD_TGID,
111 LTT_FIELD_CHILD_TGID,
112 LTT_FIELD_FILENAME,
113 LTT_FIELD_NAME,
114 LTT_FIELD_TYPE,
115 LTT_FIELD_MODE,
116 LTT_FIELD_SUBMODE,
117 LTT_FIELD_STATUS,
118 LTT_FIELD_THIS_FN,
119 LTT_FIELD_CALL_SITE,
120 LTT_FIELD_MINOR,
121 LTT_FIELD_MAJOR,
122 LTT_FIELD_OPERATION,
123 LTT_FIELD_ACTION,
124 LTT_FIELD_ID,
125 LTT_FIELD_ADDRESS,
126 LTT_FIELD_SYMBOL,
127 LTT_FIELD_IP,
128 LTT_FIELD_FD,
129 LTT_FIELD_STATE,
130 LTT_FIELD_CPU_ID;
eed2ef37 131
b445142a 132LttvExecutionMode
90e19f82
AM
133 LTTV_STATE_MODE_UNKNOWN,
134 LTTV_STATE_USER_MODE,
f044974e 135 LTTV_STATE_MAYBE_USER_MODE,
90e19f82 136 LTTV_STATE_SYSCALL,
f044974e 137 LTTV_STATE_MAYBE_SYSCALL,
90e19f82 138 LTTV_STATE_TRAP,
f044974e 139 LTTV_STATE_MAYBE_TRAP,
90e19f82
AM
140 LTTV_STATE_IRQ,
141 LTTV_STATE_SOFT_IRQ;
ffd54a90 142
b445142a 143LttvExecutionSubmode
90e19f82
AM
144 LTTV_STATE_SUBMODE_UNKNOWN,
145 LTTV_STATE_SUBMODE_NONE;
ffd54a90 146
147LttvProcessStatus
90e19f82
AM
148 LTTV_STATE_UNNAMED,
149 LTTV_STATE_WAIT_FORK,
150 LTTV_STATE_WAIT_CPU,
151 LTTV_STATE_EXIT,
152 LTTV_STATE_ZOMBIE,
153 LTTV_STATE_WAIT,
154 LTTV_STATE_RUN,
155 LTTV_STATE_DEAD;
ffd54a90 156
c4a72569 157GQuark
90e19f82 158 LTTV_STATE_UNBRANDED;
c4a72569 159
e62e7f3a 160LttvProcessType
90e19f82
AM
161 LTTV_STATE_USER_THREAD,
162 LTTV_STATE_KERNEL_THREAD;
e62e7f3a 163
44ffb95f 164LttvCPUMode
90e19f82
AM
165 LTTV_CPU_UNKNOWN,
166 LTTV_CPU_IDLE,
167 LTTV_CPU_BUSY,
168 LTTV_CPU_IRQ,
169 LTTV_CPU_SOFT_IRQ,
170 LTTV_CPU_TRAP;
44ffb95f 171
5e563da0 172LttvIRQMode
90e19f82
AM
173 LTTV_IRQ_UNKNOWN,
174 LTTV_IRQ_IDLE,
175 LTTV_IRQ_BUSY;
5e563da0 176
27811799 177LttvBdevMode
90e19f82
AM
178 LTTV_BDEV_UNKNOWN,
179 LTTV_BDEV_IDLE,
180 LTTV_BDEV_BUSY_READING,
181 LTTV_BDEV_BUSY_WRITING;
27811799 182
ba576a78 183static GQuark
90e19f82
AM
184 LTTV_STATE_TRACEFILES,
185 LTTV_STATE_PROCESSES,
186 LTTV_STATE_PROCESS,
187 LTTV_STATE_RUNNING_PROCESS,
7a4bdb54 188 LTTV_STATE_POSITION,
90e19f82
AM
189 LTTV_STATE_SAVED_STATES,
190 LTTV_STATE_SAVED_STATES_TIME,
191 LTTV_STATE_TIME,
192 LTTV_STATE_HOOKS,
193 LTTV_STATE_NAME_TABLES,
194 LTTV_STATE_TRACE_STATE_USE_COUNT,
195 LTTV_STATE_RESOURCE_CPUS,
196 LTTV_STATE_RESOURCE_CPUS_COUNT,
197 LTTV_STATE_RESOURCE_IRQS,
198 LTTV_STATE_RESOURCE_SOFT_IRQS,
199 LTTV_STATE_RESOURCE_TRAPS,
200 LTTV_STATE_RESOURCE_BLKDEVS;
ba576a78 201
f95bc830 202static void create_max_time(LttvTraceState *tcs);
203
204static void get_max_time(LttvTraceState *tcs);
205
206static void free_max_time(LttvTraceState *tcs);
207
208static void create_name_tables(LttvTraceState *tcs);
209
210static void get_name_tables(LttvTraceState *tcs);
b445142a 211
212static void free_name_tables(LttvTraceState *tcs);
213
f95bc830 214static void free_saved_state(LttvTraceState *tcs);
215
308711e5 216static void lttv_state_free_process_table(GHashTable *processes);
ba576a78 217
7df20ca4 218static void lttv_trace_states_read_raw(LttvTraceState *tcs, FILE *fp,
90e19f82 219 GPtrArray *quarktable);
dc877563 220
44c0619e 221/* Resource function prototypes */
59dc1f2a 222static LttvBdevState *get_hashed_bdevstate(LttvTraceState *ts, guint32 devcode);
98d7814f 223static LttvBdevState *bdevstate_new(void);
224static void bdevstate_free(LttvBdevState *);
225static void bdevstate_free_cb(gpointer key, gpointer value, gpointer user_data);
226static LttvBdevState *bdevstate_copy(LttvBdevState *bds);
7a4bdb54 227void lttv_state_add_event_hooks(LttvTraceset *traceset);
44c0619e 228
e9a5b514 229#if (__WORDSIZE == 32)
9ee1ff6a 230guint guint64_hash(gconstpointer key)
231{
232 guint64 ukey = *(const guint64 *)key;
233
234 return (guint)ukey ^ (guint)(ukey >> 32);
235}
236
237gboolean guint64_equal(gconstpointer a, gconstpointer b)
238{
239 guint64 ua = *(const guint64 *)a;
240 guint64 ub = *(const guint64 *)b;
241
242 return ua == ub;
243}
244#endif
245
2a2fa4f0 246guint process_hash(gconstpointer key)
247{
90e19f82
AM
248 guint pid = ((const LttvProcessState *)key)->pid;
249 return (pid>>8 ^ pid>>4 ^ pid>>2 ^ pid) ;
2a2fa4f0 250}
251
252
1d1df11d 253/* If the hash table hash function is well distributed,
254 * the process_equal should compare different pid */
2a2fa4f0 255gboolean process_equal(gconstpointer a, gconstpointer b)
256{
90e19f82
AM
257 const LttvProcessState *process_a, *process_b;
258 gboolean ret = TRUE;
259
260 process_a = (const LttvProcessState *)a;
261 process_b = (const LttvProcessState *)b;
2a2fa4f0 262
90e19f82
AM
263 if(likely(process_a->pid != process_b->pid)) ret = FALSE;
264 else if(likely(process_a->pid == 0 &&
265 process_a->cpu != process_b->cpu)) ret = FALSE;
266
267 return ret;
2a2fa4f0 268}
269
0e2767c2 270gboolean rettrue(gpointer key, gpointer value, gpointer user_data)
271{
272 return TRUE;
273}
2a2fa4f0 274
b0e00636 275static guint check_expand(nb, id)
276{
90e19f82
AM
277 if(likely(nb > id))
278 return nb;
279 else
280 return max(id + 1, nb * 2);
b0e00636 281}
282
283static void expand_name_table(LttvTraceState *ts, GQuark **table,
90e19f82 284 guint nb, guint new_nb)
b0e00636 285{
90e19f82
AM
286 /* Expand an incomplete table */
287 GQuark *old_table = *table;
288 *table = g_new(GQuark, new_nb);
289 memcpy(*table, old_table, nb * sizeof(GQuark));
290 g_free(old_table);
b0e00636 291}
292
293static void fill_name_table(LttvTraceState *ts, GQuark *table, guint nb,
90e19f82 294 guint new_nb, const char *def_string)
b0e00636 295{
90e19f82
AM
296 guint i;
297 GString *fe_name = g_string_new("");
298 for(i = nb; i < new_nb; i++) {
299 g_string_printf(fe_name, "%s %d", def_string, i);
300 table[i] = g_quark_from_string(fe_name->str);
301 }
302 g_string_free(fe_name, TRUE);
b0e00636 303}
304
2d0d580c 305static void expand_kprobe_table(LttvTraceState *ts, guint64 ip, char *symbol)
306{
90e19f82 307 LttvNameTables *nt = ts->name_tables;
e9a5b514 308#if (__WORDSIZE == 32)
90e19f82
AM
309 guint64 *ip_ptr = g_new(guint64, 1);
310 g_hash_table_insert(nt->kprobe_hash, ip_ptr,
311 (gpointer)(glong)g_quark_from_string(symbol));
9ee1ff6a 312#else
90e19f82
AM
313 g_hash_table_insert(nt->kprobe_hash, (gpointer)ip,
314 (gpointer)(glong)g_quark_from_string(symbol));
9ee1ff6a 315#endif
2d0d580c 316}
317
b0e00636 318static void expand_trap_table(LttvTraceState *ts, int id)
319{
90e19f82
AM
320 LttvNameTables *nt = ts->name_tables;
321 LttvTrapState *old_table;
322 guint new_nb, i;
1cd9058f 323
90e19f82
AM
324 new_nb = check_expand(nt->nb_traps, id);
325 if(likely(new_nb == nt->nb_traps))
326 return;
b0e00636 327
90e19f82
AM
328 expand_name_table(ts, &nt->trap_names, nt->nb_traps, new_nb);
329 fill_name_table(ts, nt->trap_names, nt->nb_traps, new_nb, "trap");
1cd9058f 330
90e19f82
AM
331 old_table = ts->trap_states;
332 ts->trap_states = g_new(LttvTrapState, new_nb);
333 memcpy(ts->trap_states, old_table, nt->nb_traps * sizeof(LttvTrapState));
334 g_free(old_table);
335 for(i = nt->nb_traps; i < new_nb; i++)
336 ts->trap_states[i].running = 0;
1cd9058f 337
90e19f82
AM
338 /* Update the table size */
339 nt->nb_traps = new_nb;
b0e00636 340}
341
342static void expand_irq_table(LttvTraceState *ts, int id)
343{
90e19f82
AM
344 LttvNameTables *nt = ts->name_tables;
345 LttvIRQState *old_table;
346 guint new_nb, i;
1cd9058f 347
90e19f82
AM
348 new_nb = check_expand(nt->nb_irqs, id);
349 if(likely(new_nb == nt->nb_irqs))
350 return;
b0e00636 351
90e19f82
AM
352 expand_name_table(ts, &nt->irq_names, nt->nb_irqs, new_nb);
353 fill_name_table(ts, nt->irq_names, nt->nb_irqs, new_nb, "irq");
1cd9058f 354
90e19f82
AM
355 old_table = ts->irq_states;
356 ts->irq_states = g_new(LttvIRQState, new_nb);
357 memcpy(ts->irq_states, old_table, nt->nb_irqs * sizeof(LttvIRQState));
358 g_free(old_table);
359 for(i = nt->nb_irqs; i < new_nb; i++)
360 ts->irq_states[i].mode_stack =
361 g_array_new(FALSE, FALSE, sizeof(LttvIRQMode));
b0e00636 362
90e19f82
AM
363 /* Update the table size */
364 nt->nb_irqs = new_nb;
b0e00636 365}
366
367static void expand_soft_irq_table(LttvTraceState *ts, int id)
368{
90e19f82
AM
369 LttvNameTables *nt = ts->name_tables;
370 LttvSoftIRQState *old_table;
371 guint new_nb, i;
372
373 new_nb = check_expand(nt->nb_soft_irqs, id);
374 if(likely(new_nb == nt->nb_soft_irqs))
375 return;
376
377 expand_name_table(ts, &nt->soft_irq_names, nt->nb_soft_irqs, new_nb);
378 fill_name_table(ts, nt->soft_irq_names, nt->nb_soft_irqs, new_nb, "softirq");
379
380 old_table = ts->soft_irq_states;
381 ts->soft_irq_states = g_new(LttvSoftIRQState, new_nb);
382 memcpy(ts->soft_irq_states, old_table,
383 nt->nb_soft_irqs * sizeof(LttvSoftIRQState));
384 g_free(old_table);
385 for(i = nt->nb_soft_irqs; i < new_nb; i++)
386 ts->soft_irq_states[i].running = 0;
387
388 /* Update the table size */
389 nt->nb_soft_irqs = new_nb;
390}
391
392static void restore_init_state(LttvTraceState *self)
393{
394 guint i, nb_cpus, nb_irqs, nb_soft_irqs, nb_traps;
395
396 //LttvTracefileState *tfcs;
397
afdfc849 398 LttTime start_time;
90e19f82
AM
399
400 /* Free the process tables */
401 if(self->processes != NULL) lttv_state_free_process_table(self->processes);
90e19f82 402 self->processes = g_hash_table_new(process_hash, process_equal);
90e19f82
AM
403 self->nb_event = 0;
404
405 /* Seek time to beginning */
406 // Mathieu : fix : don't seek traceset here : causes inconsistency in seek
407 // closest. It's the tracecontext job to seek the trace to the beginning
408 // anyway : the init state might be used at the middle of the trace as well...
409 //g_tree_destroy(self->parent.ts_context->pqueue);
410 //self->parent.ts_context->pqueue = g_tree_new(compare_tracefile);
411
afdfc849
YB
412 start_time = ltt_time_from_uint64(
413 bt_trace_handle_get_timestamp_begin(self->trace->traceset->context,
414 self->trace->id));
415
90e19f82
AM
416
417 //lttv_process_trace_seek_time(&self->parent, ltt_time_zero);
418
7a4bdb54 419 nb_cpus = lttv_trace_get_num_cpu(self->trace);
90e19f82
AM
420 nb_irqs = self->name_tables->nb_irqs;
421 nb_soft_irqs = self->name_tables->nb_soft_irqs;
422 nb_traps = self->name_tables->nb_traps;
423
424 /* Put the per cpu running_process to beginning state : process 0. */
425 for(i=0; i< nb_cpus; i++) {
426 LttvExecutionState *es;
427 self->running_process[i] = lttv_state_create_process(self, NULL, i, 0, 0,
afdfc849 428 LTTV_STATE_UNNAMED, &start_time);
90e19f82
AM
429 /* We are not sure is it's a kernel thread or normal thread, put the
430 * bottom stack state to unknown */
431 self->running_process[i]->execution_stack =
432 g_array_set_size(self->running_process[i]->execution_stack, 1);
433 es = self->running_process[i]->state =
434 &g_array_index(self->running_process[i]->execution_stack,
435 LttvExecutionState, 0);
436 es->t = LTTV_STATE_MODE_UNKNOWN;
437 es->s = LTTV_STATE_UNNAMED;
438
439 //self->running_process[i]->state->s = LTTV_STATE_RUN;
440 self->running_process[i]->cpu = i;
441
442 /* reset cpu states */
443 if(self->cpu_states[i].mode_stack->len > 0) {
444 g_array_remove_range(self->cpu_states[i].mode_stack, 0,
445 self->cpu_states[i].mode_stack->len);
446 if(self->cpu_states[i].irq_stack->len)
447 g_array_remove_range(self->cpu_states[i].irq_stack, 0,
448 self->cpu_states[i].irq_stack->len);
449 if(self->cpu_states[i].softirq_stack->len)
450 g_array_remove_range(self->cpu_states[i].softirq_stack, 0,
451 self->cpu_states[i].softirq_stack->len);
452 if(self->cpu_states[i].trap_stack->len)
453 g_array_remove_range(self->cpu_states[i].trap_stack, 0,
454 self->cpu_states[i].trap_stack->len);
455 }
456 }
457
458 /* reset irq states */
459 for(i=0; i<nb_irqs; i++) {
460 if(self->irq_states[i].mode_stack->len > 0)
461 g_array_remove_range(self->irq_states[i].mode_stack, 0,
462 self->irq_states[i].mode_stack->len);
463 }
464
465 /* reset softirq states */
466 for(i=0; i<nb_soft_irqs; i++) {
467 self->soft_irq_states[i].pending = 0;
468 self->soft_irq_states[i].running = 0;
469 }
470
471 /* reset trap states */
472 for(i=0; i<nb_traps; i++) {
473 self->trap_states[i].running = 0;
474 }
475
476 /* reset bdev states */
477 g_hash_table_foreach(self->bdev_states, bdevstate_free_cb, NULL);
478 //g_hash_table_steal_all(self->bdev_states);
479 g_hash_table_foreach_steal(self->bdev_states, rettrue, NULL);
480
348c6ba8 481#if 0
90e19f82
AM
482 nb_tracefile = self->parent.tracefiles->len;
483
484 for(i = 0 ; i < nb_tracefile ; i++) {
485 tfcs =
486 LTTV_TRACEFILE_STATE(g_array_index(self->parent.tracefiles,
487 LttvTracefileContext*, i));
488 ltt_trace_time_span_get(self->parent.t, &tfcs->parent.timestamp, NULL);
489// tfcs->saved_position = 0;
490 tfcs->process = lttv_state_create_process(tfcs, NULL,0);
491 tfcs->process->state->s = LTTV_STATE_RUN;
492 tfcs->process->last_cpu = tfcs->cpu_name;
493 tfcs->process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfcs)->tf);
494 }
348c6ba8 495#endif //0
308711e5 496}
497
348c6ba8 498//static LttTime time_zero = {0,0};
308711e5 499
7a4bdb54 500#ifdef BABEL_CLEANUP
6806b3c6 501
7df20ca4 502#define MAX_STRING_LEN 4096
503
90e19f82
AM
504static void state_load_saved_states(LttvTraceState *tcs)
505{
506 FILE *fp;
507 GPtrArray *quarktable;
508 const char *trace_path;
509 char path[PATH_MAX];
510 guint count;
511 guint i;
512 tcs->has_precomputed_states = FALSE;
513 GQuark q;
514 gchar *string;
515 gint hdr;
516 gchar buf[MAX_STRING_LEN];
517 guint len;
bdddf3f5 518 size_t res;
90e19f82
AM
519
520 trace_path = g_quark_to_string(ltt_trace_name(tcs->parent.t));
521 strncpy(path, trace_path, PATH_MAX-1);
522 count = strnlen(trace_path, PATH_MAX-1);
523 // quarktable : open, test
524 strncat(path, "/precomputed/quarktable", PATH_MAX-count-1);
525 fp = fopen(path, "r");
526 if(!fp) return;
527 quarktable = g_ptr_array_sized_new(4096);
528
529 /* Index 0 is null */
530 hdr = fgetc(fp);
531 if(hdr == EOF) return;
532 g_assert(hdr == HDR_QUARKS);
533 q = 1;
534 do {
535 hdr = fgetc(fp);
536 if(hdr == EOF) break;
537 g_assert(hdr == HDR_QUARK);
538 g_ptr_array_set_size(quarktable, q+1);
539 i=0;
540 while(1) {
bdddf3f5
AM
541 res = fread(&buf[i], sizeof(gchar), 1, fp);
542 g_assert(res == 1);
90e19f82
AM
543 if(buf[i] == '\0' || feof(fp)) break;
544 i++;
545 }
546 len = strnlen(buf, MAX_STRING_LEN-1);
547 g_ptr_array_index (quarktable, q) = g_new(gchar, len+1);
548 strncpy(g_ptr_array_index (quarktable, q), buf, len+1);
549 q++;
550 } while(1);
551
552 fclose(fp);
553
554 // saved_states : open, test
555 strncpy(path, trace_path, PATH_MAX-1);
556 count = strnlen(trace_path, PATH_MAX-1);
557 strncat(path, "/precomputed/states", PATH_MAX-count-1);
558 fp = fopen(path, "r");
559 if(!fp) return;
560
561 hdr = fgetc(fp);
562 if(hdr != HDR_TRACE) goto end;
563
564 lttv_trace_states_read_raw(tcs, fp, quarktable);
565
566 tcs->has_precomputed_states = TRUE;
7df20ca4 567
568end:
90e19f82 569 fclose(fp);
5e563da0 570
90e19f82
AM
571 /* Free the quarktable */
572 for(i=0; i<quarktable->len; i++) {
573 string = g_ptr_array_index (quarktable, i);
574 g_free(string);
575 }
576 g_ptr_array_free(quarktable, TRUE);
577 return;
578}
7a4bdb54 579#endif /* BABEL_CLEANUP */
90e19f82 580
7a4bdb54 581void lttv_trace_state_init(LttvTraceState *trace_state, LttvTrace *trace)
90e19f82 582{
7a4bdb54 583 guint j, nb_cpu;
90e19f82 584 guint64 nb_irq;
90e19f82
AM
585 LttvAttributeValue v;
586
7a4bdb54 587 trace_state->trace = trace;
90e19f82 588
7a4bdb54
YB
589 trace_state->save_interval = LTTV_STATE_SAVE_INTERVAL;
590 lttv_attribute_find(lttv_trace_attribute(trace), LTTV_STATE_TRACE_STATE_USE_COUNT,
591 LTTV_UINT, &v);
592 (*v.v_uint)++;
2bc1bcfb 593
7a4bdb54
YB
594 if (*(v.v_uint) == 1) {
595 create_name_tables(trace_state);
596 create_max_time(trace_state);
597 }
598 get_name_tables(trace_state);
599 get_max_time(trace_state);
600
601 nb_cpu = lttv_trace_get_num_cpu(trace);
602 nb_irq = trace_state->name_tables->nb_irqs;
603 trace_state->processes = NULL;
604 trace_state->running_process = g_new(LttvProcessState*, nb_cpu);
605
606 /* init cpu resource stuff */
607 trace_state->cpu_states = g_new(LttvCPUState, nb_cpu);
608 for (j = 0; j < nb_cpu; j++) {
609 trace_state->cpu_states[j].mode_stack = g_array_new(FALSE, FALSE, sizeof(LttvCPUMode));
610 trace_state->cpu_states[j].irq_stack = g_array_new(FALSE, FALSE, sizeof(gint));
611 trace_state->cpu_states[j].softirq_stack = g_array_new(FALSE, FALSE, sizeof(gint));
612 trace_state->cpu_states[j].trap_stack = g_array_new(FALSE, FALSE, sizeof(gint));
613 g_assert(trace_state->cpu_states[j].mode_stack != NULL);
614 }
90e19f82 615
7a4bdb54
YB
616 /* init irq resource stuff */
617 trace_state->irq_states = g_new(LttvIRQState, nb_irq);
618 for (j = 0; j < nb_irq; j++) {
619 trace_state->irq_states[j].mode_stack = g_array_new(FALSE, FALSE, sizeof(LttvIRQMode));
620 g_assert(trace_state->irq_states[j].mode_stack != NULL);
621 }
90e19f82 622
7a4bdb54
YB
623 /* init soft irq stuff */
624 /* the kernel has a statically fixed max of 32 softirqs */
625 trace_state->soft_irq_states = g_new(LttvSoftIRQState, trace_state->name_tables->nb_soft_irqs);
90e19f82 626
7a4bdb54
YB
627 /* init trap stuff */
628 trace_state->trap_states = g_new(LttvTrapState, trace_state->name_tables->nb_traps);
90e19f82 629
7a4bdb54
YB
630 /* init bdev resource stuff */
631 trace_state->bdev_states = g_hash_table_new(g_int_hash, g_int_equal);
90e19f82 632
7a4bdb54 633 restore_init_state(trace_state);
90e19f82 634
7a4bdb54
YB
635 /* See if the trace has saved states */
636 //state_load_saved_states(trace_state);
90e19f82 637}
38726a78 638
7a4bdb54 639void lttv_trace_state_fini(LttvTraceState *trace_state)
90e19f82 640{
7a4bdb54 641 LttvTrace *trace = trace_state->trace;
90e19f82 642 LttvAttributeValue v;
dc877563 643
7a4bdb54
YB
644 lttv_attribute_find(lttv_trace_attribute(trace), LTTV_STATE_TRACE_STATE_USE_COUNT,
645 LTTV_UINT, &v);
dc877563 646
7a4bdb54
YB
647 g_assert(*(v.v_uint) != 0);
648 (*v.v_uint)--;
dc877563 649
7a4bdb54
YB
650 if (*(v.v_uint) == 0) {
651 free_name_tables(trace_state);
652 free_max_time(trace_state);
653 free_saved_state(trace_state);
90e19f82 654 }
7a4bdb54
YB
655 g_free(trace_state->running_process);
656 trace_state->running_process = NULL;
657 lttv_state_free_process_table(trace_state->processes);
658 trace_state->processes = NULL;
ffd54a90 659}
660
7a4bdb54 661#ifdef BABEL_CLEANUP
ffd54a90 662
dbb7bb09 663/* Write the process state of the trace */
664
665static void write_process_state(gpointer key, gpointer value,
90e19f82 666 gpointer user_data)
dbb7bb09 667{
90e19f82 668 LttvProcessState *process;
dbb7bb09 669
90e19f82 670 LttvExecutionState *es;
dbb7bb09 671
90e19f82
AM
672 FILE *fp = (FILE *)user_data;
673
674 guint i;
675 guint64 address;
676
677 process = (LttvProcessState *)value;
678 fprintf(fp," <PROCESS CORE=%p PID=%u TGID=%u PPID=%u TYPE=\"%s\" CTIME_S=%lu CTIME_NS=%lu ITIME_S=%lu ITIME_NS=%lu NAME=\"%s\" BRAND=\"%s\" CPU=\"%u\" FREE_EVENTS=\"%u\">\n",
679 process, process->pid, process->tgid, process->ppid,
680 g_quark_to_string(process->type),
681 process->creation_time.tv_sec,
682 process->creation_time.tv_nsec,
683 process->insertion_time.tv_sec,
684 process->insertion_time.tv_nsec,
685 g_quark_to_string(process->name),
686 g_quark_to_string(process->brand),
687 process->cpu, process->free_events);
688
689 for(i = 0 ; i < process->execution_stack->len; i++) {
690 es = &g_array_index(process->execution_stack, LttvExecutionState, i);
691 fprintf(fp, " <ES MODE=\"%s\" SUBMODE=\"%s\" ENTRY_S=%lu ENTRY_NS=%lu",
692 g_quark_to_string(es->t), g_quark_to_string(es->n),
693 es->entry.tv_sec, es->entry.tv_nsec);
694 fprintf(fp, " CHANGE_S=%lu CHANGE_NS=%lu STATUS=\"%s\"/>\n",
695 es->change.tv_sec, es->change.tv_nsec, g_quark_to_string(es->s));
696 }
d4dd4885 697
90e19f82
AM
698 for(i = 0 ; i < process->user_stack->len; i++) {
699 address = g_array_index(process->user_stack, guint64, i);
700 fprintf(fp, " <USER_STACK ADDRESS=\"%" PRIu64 "\"/>\n", address);
701 }
d4dd4885 702
90e19f82 703 fprintf(fp, " </PROCESS>\n");
dbb7bb09 704}
705
706
707void lttv_state_write(LttvTraceState *self, LttTime t, FILE *fp)
708{
90e19f82
AM
709 guint i, nb_tracefile, nb_block, offset;
710 guint64 tsc;
dbb7bb09 711
90e19f82 712 LttvTracefileState *tfcs;
dbb7bb09 713
90e19f82 714 LttTracefile *tf;
dbb7bb09 715
90e19f82 716 LttEventPosition *ep;
dbb7bb09 717
90e19f82 718 guint nb_cpus;
348c6ba8 719
90e19f82 720 ep = ltt_event_position_new();
dbb7bb09 721
90e19f82 722 fprintf(fp,"<PROCESS_STATE TIME_S=%lu TIME_NS=%lu>\n", t.tv_sec, t.tv_nsec);
dbb7bb09 723
90e19f82 724 g_hash_table_foreach(self->processes, write_process_state, fp);
dbb7bb09 725
90e19f82
AM
726 nb_cpus = ltt_trace_get_num_cpu(self->parent.t);
727 for(i=0;i<nb_cpus;i++) {
728 fprintf(fp," <CPU NUM=%u RUNNING_PROCESS=%u>\n",
729 i, self->running_process[i]->pid);
730 }
dbb7bb09 731
90e19f82
AM
732 nb_tracefile = self->parent.tracefiles->len;
733
734 for(i = 0 ; i < nb_tracefile ; i++) {
735 tfcs =
736 LTTV_TRACEFILE_STATE(g_array_index(self->parent.tracefiles,
737 LttvTracefileContext*, i));
738 fprintf(fp, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
739 tfcs->parent.timestamp.tv_sec,
740 tfcs->parent.timestamp.tv_nsec);
741 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.tf);
742 if(e == NULL) fprintf(fp,"/>\n");
743 else {
744 ltt_event_position(e, ep);
745 ltt_event_position_get(ep, &tf, &nb_block, &offset, &tsc);
746 fprintf(fp, " BLOCK=%u OFFSET=%u TSC=%" PRIu64 "/>\n", nb_block, offset,
747 tsc);
748 }
749 }
750 g_free(ep);
751 fprintf(fp,"</PROCESS_STATE>\n");
6d0cdf22 752}
753
754
755static void write_process_state_raw(gpointer key, gpointer value,
90e19f82
AM
756 gpointer user_data)
757{
758 LttvProcessState *process;
759
760 LttvExecutionState *es;
761
762 FILE *fp = (FILE *)user_data;
763
764 guint i;
765 guint64 address;
766
767 process = (LttvProcessState *)value;
768 fputc(HDR_PROCESS, fp);
769 //fwrite(&header, sizeof(header), 1, fp);
770 //fprintf(fp, "%s", g_quark_to_string(process->type));
771 //fputc('\0', fp);
772 fwrite(&process->type, sizeof(process->type), 1, fp);
773 //fprintf(fp, "%s", g_quark_to_string(process->name));
774 //fputc('\0', fp);
775 fwrite(&process->name, sizeof(process->name), 1, fp);
776 //fprintf(fp, "%s", g_quark_to_string(process->brand));
777 //fputc('\0', fp);
778 fwrite(&process->brand, sizeof(process->brand), 1, fp);
779 fwrite(&process->pid, sizeof(process->pid), 1, fp);
780 fwrite(&process->free_events, sizeof(process->free_events), 1, fp);
781 fwrite(&process->tgid, sizeof(process->tgid), 1, fp);
782 fwrite(&process->ppid, sizeof(process->ppid), 1, fp);
783 fwrite(&process->cpu, sizeof(process->cpu), 1, fp);
784 fwrite(&process->creation_time, sizeof(process->creation_time), 1, fp);
785 fwrite(&process->insertion_time, sizeof(process->insertion_time), 1, fp);
6d0cdf22 786
787#if 0
90e19f82
AM
788 fprintf(fp," <PROCESS CORE=%p PID=%u TGID=%u PPID=%u TYPE=\"%s\" CTIME_S=%lu CTIME_NS=%lu ITIME_S=%lu ITIME_NS=%lu NAME=\"%s\" BRAND=\"%s\" CPU=\"%u\" PROCESS_TYPE=%u>\n",
789 process, process->pid, process->tgid, process->ppid,
790 g_quark_to_string(process->type),
791 process->creation_time.tv_sec,
792 process->creation_time.tv_nsec,
793 process->insertion_time.tv_sec,
794 process->insertion_time.tv_nsec,
795 g_quark_to_string(process->name),
796 g_quark_to_string(process->brand),
797 process->cpu);
6d0cdf22 798#endif //0
799
90e19f82
AM
800 for(i = 0 ; i < process->execution_stack->len; i++) {
801 es = &g_array_index(process->execution_stack, LttvExecutionState, i);
802
803 fputc(HDR_ES, fp);
804 //fprintf(fp, "%s", g_quark_to_string(es->t));
805 //fputc('\0', fp);
806 fwrite(&es->t, sizeof(es->t), 1, fp);
807 //fprintf(fp, "%s", g_quark_to_string(es->n));
808 //fputc('\0', fp);
809 fwrite(&es->n, sizeof(es->n), 1, fp);
810 //fprintf(fp, "%s", g_quark_to_string(es->s));
811 //fputc('\0', fp);
812 fwrite(&es->s, sizeof(es->s), 1, fp);
813 fwrite(&es->entry, sizeof(es->entry), 1, fp);
814 fwrite(&es->change, sizeof(es->change), 1, fp);
815 fwrite(&es->cum_cpu_time, sizeof(es->cum_cpu_time), 1, fp);
6d0cdf22 816#if 0
90e19f82
AM
817 fprintf(fp, " <ES MODE=\"%s\" SUBMODE=\"%s\" ENTRY_S=%lu ENTRY_NS=%lu",
818 g_quark_to_string(es->t), g_quark_to_string(es->n),
819 es->entry.tv_sec, es->entry.tv_nsec);
820 fprintf(fp, " CHANGE_S=%lu CHANGE_NS=%lu STATUS=\"%s\"/>\n",
821 es->change.tv_sec, es->change.tv_nsec, g_quark_to_string(es->s));
6d0cdf22 822#endif //0
90e19f82 823 }
6d0cdf22 824
90e19f82
AM
825 for(i = 0 ; i < process->user_stack->len; i++) {
826 address = g_array_index(process->user_stack, guint64, i);
827 fputc(HDR_USER_STACK, fp);
828 fwrite(&address, sizeof(address), 1, fp);
6d0cdf22 829#if 0
90e19f82 830 fprintf(fp, " <USER_STACK ADDRESS=\"%llu\"/>\n", address);
6d0cdf22 831#endif //0
90e19f82 832 }
dbb7bb09 833}
834
835
6d0cdf22 836void lttv_state_write_raw(LttvTraceState *self, LttTime t, FILE *fp)
837{
90e19f82
AM
838 guint i, nb_tracefile, nb_block, offset;
839 guint64 tsc;
840
841 LttvTracefileState *tfcs;
842
843 LttTracefile *tf;
844
845 LttEventPosition *ep;
846
847 guint nb_cpus;
848
849 ep = ltt_event_position_new();
850
851 //fprintf(fp,"<PROCESS_STATE TIME_S=%lu TIME_NS=%lu>\n", t.tv_sec, t.tv_nsec);
852 fputc(HDR_PROCESS_STATE, fp);
853 fwrite(&t, sizeof(t), 1, fp);
854
855 g_hash_table_foreach(self->processes, write_process_state_raw, fp);
856
857 nb_cpus = ltt_trace_get_num_cpu(self->parent.t);
858 for(i=0;i<nb_cpus;i++) {
859 fputc(HDR_CPU, fp);
860 fwrite(&i, sizeof(i), 1, fp); /* cpu number */
861 fwrite(&self->running_process[i]->pid,
862 sizeof(self->running_process[i]->pid), 1, fp);
863 //fprintf(fp," <CPU NUM=%u RUNNING_PROCESS=%u>\n",
864 // i, self->running_process[i]->pid);
865 }
866
867 nb_tracefile = self->parent.tracefiles->len;
868
869 for(i = 0 ; i < nb_tracefile ; i++) {
870 tfcs =
871 LTTV_TRACEFILE_STATE(g_array_index(self->parent.tracefiles,
872 LttvTracefileContext*, i));
873 // fprintf(fp, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
874 // tfcs->parent.timestamp.tv_sec,
875 // tfcs->parent.timestamp.tv_nsec);
876 fputc(HDR_TRACEFILE, fp);
877 fwrite(&tfcs->parent.timestamp, sizeof(tfcs->parent.timestamp), 1, fp);
878 /* Note : if timestamp if LTT_TIME_INFINITE, there will be no
879 * position following : end of trace */
880 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.tf);
881 if(e != NULL) {
882 ltt_event_position(e, ep);
883 ltt_event_position_get(ep, &tf, &nb_block, &offset, &tsc);
884 //fprintf(fp, " BLOCK=%u OFFSET=%u TSC=%llu/>\n", nb_block, offset,
885 // tsc);
886 fwrite(&nb_block, sizeof(nb_block), 1, fp);
887 fwrite(&offset, sizeof(offset), 1, fp);
888 fwrite(&tsc, sizeof(tsc), 1, fp);
889 }
890 }
891 g_free(ep);
6d0cdf22 892}
893
894
895/* Read process state from a file */
896
897/* Called because a HDR_PROCESS was found */
7df20ca4 898static void read_process_state_raw(LttvTraceState *self, FILE *fp,
90e19f82
AM
899 GPtrArray *quarktable)
900{
901 LttvExecutionState *es;
902 LttvProcessState *process, *parent_process;
903 LttvProcessState tmp;
904 GQuark tmpq;
bdddf3f5 905 size_t res;
90e19f82
AM
906
907 guint64 *address;
908
bdddf3f5
AM
909 res = fread(&tmp.type, sizeof(tmp.type), 1, fp);
910 res += fread(&tmp.name, sizeof(tmp.name), 1, fp);
911 res += fread(&tmp.brand, sizeof(tmp.brand), 1, fp);
912 res += fread(&tmp.pid, sizeof(tmp.pid), 1, fp);
913 res += fread(&tmp.free_events, sizeof(tmp.free_events), 1, fp);
914 res += fread(&tmp.tgid, sizeof(tmp.tgid), 1, fp);
915 res += fread(&tmp.ppid, sizeof(tmp.ppid), 1, fp);
916 res += fread(&tmp.cpu, sizeof(tmp.cpu), 1, fp);
917 res += fread(&tmp.creation_time, sizeof(tmp.creation_time), 1, fp);
918 res += fread(&tmp.insertion_time, sizeof(tmp.insertion_time), 1, fp);
919 g_assert(res == 10);
90e19f82
AM
920
921 if(tmp.pid == 0) {
922 process = lttv_state_find_process(self, tmp.cpu, tmp.pid);
923 } else {
924 /* We must link to the parent */
925 parent_process = lttv_state_find_process_or_create(self, ANY_CPU, tmp.ppid,
926 &ltt_time_zero);
927 process = lttv_state_find_process(self, ANY_CPU, tmp.pid);
928 if(process == NULL) {
929 process = lttv_state_create_process(self, parent_process, tmp.cpu,
930 tmp.pid, tmp.tgid,
931 g_quark_from_string((gchar*)g_ptr_array_index(quarktable, tmp.name)),
932 &tmp.creation_time);
933 }
934 }
935 process->insertion_time = tmp.insertion_time;
936 process->creation_time = tmp.creation_time;
937 process->type = g_quark_from_string(
938 (gchar*)g_ptr_array_index(quarktable, tmp.type));
939 process->tgid = tmp.tgid;
940 process->ppid = tmp.ppid;
941 process->brand = g_quark_from_string(
942 (gchar*)g_ptr_array_index(quarktable, tmp.brand));
943 process->name =
944 g_quark_from_string((gchar*)g_ptr_array_index(quarktable, tmp.name));
945 process->free_events = tmp.free_events;
946
947 do {
948 if(feof(fp) || ferror(fp)) goto end_loop;
949
950 gint hdr = fgetc(fp);
951 if(hdr == EOF) goto end_loop;
952
953 switch(hdr) {
954 case HDR_ES:
955 process->execution_stack =
956 g_array_set_size(process->execution_stack,
957 process->execution_stack->len + 1);
958 es = &g_array_index(process->execution_stack, LttvExecutionState,
959 process->execution_stack->len-1);
960 process->state = es;
961
bdddf3f5
AM
962 res = fread(&es->t, sizeof(es->t), 1, fp);
963 g_assert(res == 1);
90e19f82
AM
964 es->t = g_quark_from_string(
965 (gchar*)g_ptr_array_index(quarktable, es->t));
bdddf3f5
AM
966 res = fread(&es->n, sizeof(es->n), 1, fp);
967 g_assert(res == 1);
90e19f82
AM
968 es->n = g_quark_from_string(
969 (gchar*)g_ptr_array_index(quarktable, es->n));
bdddf3f5
AM
970 res = fread(&es->s, sizeof(es->s), 1, fp);
971 g_assert(res == 1);
90e19f82
AM
972 es->s = g_quark_from_string(
973 (gchar*)g_ptr_array_index(quarktable, es->s));
bdddf3f5
AM
974 res = fread(&es->entry, sizeof(es->entry), 1, fp);
975 res += fread(&es->change, sizeof(es->change), 1, fp);
976 res += fread(&es->cum_cpu_time, sizeof(es->cum_cpu_time), 1, fp);
977 g_assert(res == 3);
90e19f82
AM
978 break;
979
980 case HDR_USER_STACK:
981 process->user_stack = g_array_set_size(process->user_stack,
982 process->user_stack->len + 1);
983 address = &g_array_index(process->user_stack, guint64,
984 process->user_stack->len-1);
bdddf3f5
AM
985 res = fread(address, sizeof(address), 1, fp);
986 g_assert(res == 1);
90e19f82
AM
987 process->current_function = *address;
988 break;
989
90e19f82
AM
990 default:
991 ungetc(hdr, fp);
992 goto end_loop;
993 };
994 } while(1);
6d0cdf22 995end_loop:
90e19f82 996 return;
6d0cdf22 997}
998
999
1000/* Called because a HDR_PROCESS_STATE was found */
1001/* Append a saved state to the trace states */
7df20ca4 1002void lttv_state_read_raw(LttvTraceState *self, FILE *fp, GPtrArray *quarktable)
6d0cdf22 1003{
90e19f82
AM
1004 guint i, nb_tracefile, nb_block, offset;
1005 guint64 tsc;
1006 LttvTracefileState *tfcs;
1007
1008 LttEventPosition *ep;
1009
1010 guint nb_cpus;
1011
1012 int hdr;
bdddf3f5 1013 size_t res;
90e19f82
AM
1014
1015 LttTime t;
1016
1017 LttvAttribute *saved_states_tree, *saved_state_tree;
1018
1019 LttvAttributeValue value;
1020 GTree *pqueue = self->parent.ts_context->pqueue;
1021 ep = ltt_event_position_new();
1022
1023 restore_init_state(self);
1024
bdddf3f5
AM
1025 res = fread(&t, sizeof(t), 1, fp);
1026 g_assert(res == 1);
90e19f82
AM
1027
1028 do {
1029 if(feof(fp) || ferror(fp)) goto end_loop;
1030 hdr = fgetc(fp);
1031 if(hdr == EOF) goto end_loop;
1032
1033 switch(hdr) {
1034 case HDR_PROCESS:
1035 /* Call read_process_state_raw */
1036 read_process_state_raw(self, fp, quarktable);
1037 break;
1038 case HDR_TRACEFILE:
1039 case HDR_TRACESET:
1040 case HDR_TRACE:
1041 case HDR_QUARKS:
1042 case HDR_QUARK:
1043 case HDR_ES:
1044 case HDR_USER_STACK:
90e19f82
AM
1045 case HDR_PROCESS_STATE:
1046 case HDR_CPU:
1047 ungetc(hdr, fp);
1048 goto end_loop;
1049 break;
1050 default:
1051 g_error("Error while parsing saved state file : unknown data header %d",
1052 hdr);
1053 };
1054 } while(1);
6d0cdf22 1055end_loop:
1056
90e19f82
AM
1057 nb_cpus = ltt_trace_get_num_cpu(self->parent.t);
1058 for(i=0;i<nb_cpus;i++) {
1059 int cpu_num;
1060 hdr = fgetc(fp);
1061 g_assert(hdr == HDR_CPU);
bdddf3f5
AM
1062 res = fread(&cpu_num, sizeof(cpu_num), 1, fp); /* cpu number */
1063 g_assert(res == 1);
90e19f82 1064 g_assert(i == cpu_num);
bdddf3f5 1065 res = fread(&self->running_process[i]->pid,
90e19f82 1066 sizeof(self->running_process[i]->pid), 1, fp);
bdddf3f5 1067 g_assert(res == 1);
90e19f82
AM
1068 }
1069
1070 nb_tracefile = self->parent.tracefiles->len;
1071
1072 for(i = 0 ; i < nb_tracefile ; i++) {
1073 tfcs =
1074 LTTV_TRACEFILE_STATE(g_array_index(self->parent.tracefiles,
1075 LttvTracefileContext*, i));
1076 // fprintf(fp, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
1077 // tfcs->parent.timestamp.tv_sec,
1078 // tfcs->parent.timestamp.tv_nsec);
1079 g_tree_remove(pqueue, &tfcs->parent);
1080 hdr = fgetc(fp);
1081 g_assert(hdr == HDR_TRACEFILE);
bdddf3f5
AM
1082 res = fread(&tfcs->parent.timestamp, sizeof(tfcs->parent.timestamp), 1, fp);
1083 g_assert(res == 1);
90e19f82
AM
1084 /* Note : if timestamp if LTT_TIME_INFINITE, there will be no
1085 * position following : end of trace */
1086 if(ltt_time_compare(tfcs->parent.timestamp, ltt_time_infinite) != 0) {
bdddf3f5
AM
1087 res = fread(&nb_block, sizeof(nb_block), 1, fp);
1088 res += fread(&offset, sizeof(offset), 1, fp);
1089 res += fread(&tsc, sizeof(tsc), 1, fp);
1090 g_assert(res == 3);
90e19f82
AM
1091 ltt_event_position_set(ep, tfcs->parent.tf, nb_block, offset, tsc);
1092 gint ret = ltt_tracefile_seek_position(tfcs->parent.tf, ep);
1093 g_assert(ret == 0);
1094 g_tree_insert(pqueue, &tfcs->parent, &tfcs->parent);
1095 }
1096 }
1097 g_free(ep);
1098
1099 saved_states_tree = lttv_attribute_find_subdir(self->parent.t_a,
1100 LTTV_STATE_SAVED_STATES);
1101 saved_state_tree = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
1102 value = lttv_attribute_add(saved_states_tree,
1103 lttv_attribute_get_number(saved_states_tree), LTTV_GOBJECT);
1104 *(value.v_gobject) = (GObject *)saved_state_tree;
1105 value = lttv_attribute_add(saved_state_tree, LTTV_STATE_TIME, LTTV_TIME);
1106 *(value.v_time) = t;
1107 lttv_state_save(self, saved_state_tree);
1108 g_debug("Saving state at time %lu.%lu", t.tv_sec,
1109 t.tv_nsec);
1110
1111 *(self->max_time_state_recomputed_in_seek) = t;
ce05e187 1112
6d0cdf22 1113}
1114
1115/* Called when a HDR_TRACE is found */
7df20ca4 1116void lttv_trace_states_read_raw(LttvTraceState *tcs, FILE *fp,
90e19f82
AM
1117 GPtrArray *quarktable)
1118{
1119 int hdr;
1120
1121 do {
1122 if(feof(fp) || ferror(fp)) goto end_loop;
1123 hdr = fgetc(fp);
1124 if(hdr == EOF) goto end_loop;
1125
1126 switch(hdr) {
1127 case HDR_PROCESS_STATE:
1128 /* Call read_process_state_raw */
1129 lttv_state_read_raw(tcs, fp, quarktable);
1130 break;
1131 case HDR_TRACEFILE:
1132 case HDR_TRACESET:
1133 case HDR_TRACE:
1134 case HDR_QUARKS:
1135 case HDR_QUARK:
1136 case HDR_ES:
1137 case HDR_USER_STACK:
90e19f82
AM
1138 case HDR_PROCESS:
1139 case HDR_CPU:
1140 g_error("Error while parsing saved state file :"
1141 " unexpected data header %d",
1142 hdr);
1143 break;
1144 default:
1145 g_error("Error while parsing saved state file : unknown data header %d",
1146 hdr);
1147 };
1148 } while(1);
6d0cdf22 1149end_loop:
90e19f82
AM
1150 *(tcs->max_time_state_recomputed_in_seek) = tcs->parent.time_span.end_time;
1151 restore_init_state(tcs);
1152 lttv_process_trace_seek_time(&tcs->parent, ltt_time_zero);
1153 return;
6d0cdf22 1154}
7a4bdb54 1155#endif /* BABEL_CLEANUP */
6d0cdf22 1156
1157
dbb7bb09 1158/* Copy each process from an existing hash table to a new one */
1159
308711e5 1160static void copy_process_state(gpointer key, gpointer value,gpointer user_data)
ffd54a90 1161{
90e19f82
AM
1162 LttvProcessState *process, *new_process;
1163
1164 GHashTable *new_processes = (GHashTable *)user_data;
1165
1166 guint i;
1167
1168 process = (LttvProcessState *)value;
1169 new_process = g_new(LttvProcessState, 1);
1170 *new_process = *process;
1171 new_process->execution_stack = g_array_sized_new(FALSE, FALSE,
1172 sizeof(LttvExecutionState), PREALLOCATED_EXECUTION_STACK);
1173 new_process->execution_stack =
1174 g_array_set_size(new_process->execution_stack,
1175 process->execution_stack->len);
1176 for(i = 0 ; i < process->execution_stack->len; i++) {
1177 g_array_index(new_process->execution_stack, LttvExecutionState, i) =
1178 g_array_index(process->execution_stack, LttvExecutionState, i);
1179 }
1180 new_process->state = &g_array_index(new_process->execution_stack,
1181 LttvExecutionState, new_process->execution_stack->len - 1);
7a4bdb54 1182#ifdef BABEL_CLEANUP
90e19f82
AM
1183 new_process->user_stack = g_array_sized_new(FALSE, FALSE,
1184 sizeof(guint64), 0);
1185 new_process->user_stack = g_array_set_size(new_process->user_stack,
1186 process->user_stack->len);
1187 for(i = 0 ; i < process->user_stack->len; i++) {
1188 g_array_index(new_process->user_stack, guint64, i) =
1189 g_array_index(process->user_stack, guint64, i);
1190 }
1191 new_process->current_function = process->current_function;
7a4bdb54 1192#endif /* BABEL_CLEANUP */
90e19f82
AM
1193
1194 /* fd hash table stuff */
1195 {
1196 GHashTableIter it;
1197 gpointer key;
1198 gpointer value;
1199
1200 /* copy every item in the hash table */
1201 new_process->fds = g_hash_table_new(g_direct_hash, g_direct_equal);
1202
1203 g_hash_table_iter_init(&it, process->fds);
1204 while (g_hash_table_iter_next (&it, (void *)&key, (void *)&value)) {
1205 g_hash_table_insert(new_process->fds, key, value);
1206 }
1207 }
1208
1209 /* When done creating the new process state, insert it in the
1210 * hash table */
1211 g_hash_table_insert(new_processes, new_process, new_process);
ffd54a90 1212}
1213
1214
308711e5 1215static GHashTable *lttv_state_copy_process_table(GHashTable *processes)
ffd54a90 1216{
90e19f82 1217 GHashTable *new_processes = g_hash_table_new(process_hash, process_equal);
ffd54a90 1218
90e19f82
AM
1219 g_hash_table_foreach(processes, copy_process_state, new_processes);
1220 return new_processes;
dc877563 1221}
1222
fbfbd4db 1223static LttvCPUState *lttv_state_copy_cpu_states(LttvCPUState *states, guint n)
1224{
90e19f82
AM
1225 guint i,j;
1226 LttvCPUState *retval;
1227
1228 retval = g_new(LttvCPUState, n);
1229
1230 for(i=0; i<n; i++) {
1231 retval[i].irq_stack = g_array_new(FALSE, FALSE, sizeof(gint));
1232 g_array_set_size(retval[i].irq_stack, states[i].irq_stack->len);
1233 for(j=0; j<states[i].irq_stack->len; j++) {
1234 g_array_index(retval[i].irq_stack, gint, j) =
1235 g_array_index(states[i].irq_stack, gint, j);
1236 }
1237
1238 retval[i].softirq_stack = g_array_new(FALSE, FALSE, sizeof(gint));
1239 g_array_set_size(retval[i].softirq_stack, states[i].softirq_stack->len);
1240 for(j=0; j<states[i].softirq_stack->len; j++) {
1241 g_array_index(retval[i].softirq_stack, gint, j) =
1242 g_array_index(states[i].softirq_stack, gint, j);
1243 }
1244
1245 retval[i].trap_stack = g_array_new(FALSE, FALSE, sizeof(gint));
1246 g_array_set_size(retval[i].trap_stack, states[i].trap_stack->len);
1247 for(j=0; j<states[i].trap_stack->len; j++) {
1248 g_array_index(retval[i].trap_stack, gint, j) =
1249 g_array_index(states[i].trap_stack, gint, j);
1250 }
1251
1252 retval[i].mode_stack = g_array_new(FALSE, FALSE, sizeof(LttvCPUMode));
1253 g_array_set_size(retval[i].mode_stack, states[i].mode_stack->len);
1254 for(j=0; j<states[i].mode_stack->len; j++) {
1255 g_array_index(retval[i].mode_stack, GQuark, j) =
1256 g_array_index(states[i].mode_stack, GQuark, j);
1257 }
1258 }
fbfbd4db 1259
90e19f82 1260 return retval;
fbfbd4db 1261}
1262
1263static void lttv_state_free_cpu_states(LttvCPUState *states, guint n)
1264{
90e19f82 1265 guint i;
fbfbd4db 1266
90e19f82
AM
1267 for(i=0; i<n; i++) {
1268 g_array_free(states[i].mode_stack, TRUE);
1269 g_array_free(states[i].irq_stack, TRUE);
1270 g_array_free(states[i].softirq_stack, TRUE);
1271 g_array_free(states[i].trap_stack, TRUE);
1272 }
fbfbd4db 1273
90e19f82 1274 g_free(states);
fbfbd4db 1275}
dc877563 1276
fc6a87b2 1277static LttvIRQState *lttv_state_copy_irq_states(LttvIRQState *states, guint n)
1278{
90e19f82
AM
1279 guint i,j;
1280 LttvIRQState *retval;
fc6a87b2 1281
90e19f82 1282 retval = g_new(LttvIRQState, n);
fc6a87b2 1283
90e19f82
AM
1284 for(i=0; i<n; i++) {
1285 retval[i].mode_stack = g_array_new(FALSE, FALSE, sizeof(LttvIRQMode));
1286 g_array_set_size(retval[i].mode_stack, states[i].mode_stack->len);
1287 for(j=0; j<states[i].mode_stack->len; j++) {
1288 g_array_index(retval[i].mode_stack, GQuark, j) =
1289 g_array_index(states[i].mode_stack, GQuark, j);
1290 }
1291 }
fc6a87b2 1292
90e19f82 1293 return retval;
fc6a87b2 1294}
1295
1296static void lttv_state_free_irq_states(LttvIRQState *states, guint n)
1297{
90e19f82 1298 guint i;
fc6a87b2 1299
90e19f82
AM
1300 for(i=0; i<n; i++) {
1301 g_array_free(states[i].mode_stack, TRUE);
1302 }
fc6a87b2 1303
90e19f82 1304 g_free(states);
fc6a87b2 1305}
1306
90e19f82
AM
1307static LttvSoftIRQState *
1308lttv_state_copy_soft_irq_states(LttvSoftIRQState *states, guint n)
0305fe77 1309{
90e19f82
AM
1310 guint i;
1311 LttvSoftIRQState *retval;
0305fe77 1312
90e19f82 1313 retval = g_new(LttvSoftIRQState, n);
0305fe77 1314
90e19f82
AM
1315 for(i=0; i<n; i++) {
1316 retval[i].pending = states[i].pending;
1317 retval[i].running = states[i].running;
1318 }
0305fe77 1319
90e19f82 1320 return retval;
0305fe77 1321}
1322
61ab5e97 1323static void lttv_state_free_soft_irq_states(LttvSoftIRQState *states, guint n)
0305fe77 1324{
90e19f82 1325 g_free(states);
0305fe77 1326}
1327
90e19f82
AM
1328static LttvTrapState *
1329lttv_state_copy_trap_states(LttvTrapState *states, guint n)
38726a78 1330{
90e19f82
AM
1331 guint i;
1332 LttvTrapState *retval;
38726a78 1333
90e19f82 1334 retval = g_new(LttvTrapState, n);
38726a78 1335
90e19f82
AM
1336 for(i=0; i<n; i++) {
1337 retval[i].running = states[i].running;
1338 }
38726a78 1339
90e19f82 1340 return retval;
38726a78 1341}
1342
1343static void lttv_state_free_trap_states(LttvTrapState *states, guint n)
1344{
90e19f82 1345 g_free(states);
38726a78 1346}
1347
98d7814f 1348/* bdevstate stuff */
1349
59dc1f2a 1350static LttvBdevState *get_hashed_bdevstate(LttvTraceState *ts, guint32 devcode)
98d7814f 1351{
90e19f82
AM
1352 gint devcode_gint = devcode;
1353 gpointer bdev = g_hash_table_lookup(ts->bdev_states, &devcode_gint);
1354 if(bdev == NULL) {
1355 LttvBdevState *bdevstate = g_new(LttvBdevState, 1);
1356 bdevstate->mode_stack = g_array_new(FALSE, FALSE, sizeof(GQuark));
98d7814f 1357
90e19f82
AM
1358 gint * key = g_new(gint, 1);
1359 *key = devcode;
1360 g_hash_table_insert(ts->bdev_states, key, bdevstate);
98d7814f 1361
90e19f82
AM
1362 bdev = bdevstate;
1363 }
98d7814f 1364
90e19f82 1365 return bdev;
98d7814f 1366}
1367
1368static LttvBdevState *bdevstate_new(void)
1369{
90e19f82
AM
1370 LttvBdevState *retval;
1371 retval = g_new(LttvBdevState, 1);
1372 retval->mode_stack = g_array_new(FALSE, FALSE, sizeof(GQuark));
b895e4db 1373
90e19f82 1374 return retval;
98d7814f 1375}
1376
1377static void bdevstate_free(LttvBdevState *bds)
1378{
90e19f82
AM
1379 g_array_free(bds->mode_stack, TRUE);
1380 g_free(bds);
98d7814f 1381}
1382
1383static void bdevstate_free_cb(gpointer key, gpointer value, gpointer user_data)
1384{
90e19f82 1385 LttvBdevState *bds = (LttvBdevState *) value;
98d7814f 1386
90e19f82 1387 bdevstate_free(bds);
98d7814f 1388}
1389
1390static LttvBdevState *bdevstate_copy(LttvBdevState *bds)
1391{
90e19f82 1392 LttvBdevState *retval;
98d7814f 1393
90e19f82
AM
1394 retval = bdevstate_new();
1395 g_array_insert_vals(retval->mode_stack, 0, bds->mode_stack->data,
1396 bds->mode_stack->len);
b895e4db 1397
90e19f82 1398 return retval;
98d7814f 1399}
1400
1401static void insert_and_copy_bdev_state(gpointer k, gpointer v, gpointer u)
1402{
90e19f82
AM
1403 //GHashTable *ht = (GHashTable *)u;
1404 LttvBdevState *bds = (LttvBdevState *)v;
1405 LttvBdevState *newbds;
98d7814f 1406
90e19f82 1407 newbds = bdevstate_copy(bds);
98d7814f 1408
90e19f82 1409 g_hash_table_insert(u, k, newbds);
98d7814f 1410}
1411
1412static GHashTable *lttv_state_copy_blkdev_hashtable(GHashTable *ht)
1413{
90e19f82 1414 GHashTable *retval;
98d7814f 1415
90e19f82 1416 retval = g_hash_table_new(g_int_hash, g_int_equal);
98d7814f 1417
90e19f82 1418 g_hash_table_foreach(ht, insert_and_copy_bdev_state, retval);
98d7814f 1419
90e19f82 1420 return retval;
98d7814f 1421}
1422
1423/* Free a hashtable and the LttvBdevState structures its values
1424 * point to. */
1425
1426static void lttv_state_free_blkdev_hashtable(GHashTable *ht)
1427{
90e19f82
AM
1428 g_hash_table_foreach(ht, bdevstate_free_cb, NULL);
1429 g_hash_table_destroy(ht);
98d7814f 1430}
1431
308711e5 1432/* The saved state for each trace contains a member "processes", which
1433 stores a copy of the process table, and a member "tracefiles" with
1434 one entry per tracefile. Each tracefile has a "process" member pointing
1435 to the current process and a "position" member storing the tracefile
1436 position (needed to seek to the current "next" event. */
1437
7a4bdb54 1438void lttv_state_save(LttvTraceState *self, LttvAttribute *container)
dc877563 1439{
7a4bdb54 1440 guint i, nb_cpus, nb_irqs, nb_soft_irqs, nb_traps;
90e19f82
AM
1441
1442 guint *running_process;
1443
1444 LttvAttributeValue value;
1445
90e19f82
AM
1446 value = lttv_attribute_add(container, LTTV_STATE_PROCESSES,
1447 LTTV_POINTER);
1448 *(value.v_pointer) = lttv_state_copy_process_table(self->processes);
1449
1450 /* Add the currently running processes array */
7a4bdb54 1451 nb_cpus = lttv_trace_get_num_cpu(self->trace);
90e19f82
AM
1452 running_process = g_new(guint, nb_cpus);
1453 for(i=0;i<nb_cpus;i++) {
1454 running_process[i] = self->running_process[i]->pid;
1455 }
1456 value = lttv_attribute_add(container, LTTV_STATE_RUNNING_PROCESS,
1457 LTTV_POINTER);
1458 *(value.v_pointer) = running_process;
1459
1460 g_info("State save");
1461
7a4bdb54
YB
1462 /* Save the current position */
1463 value = lttv_attribute_add(container, LTTV_STATE_POSITION,
1464 LTTV_POINTER);
68573dd0 1465 *(value.v_pointer) = lttv_traceset_create_current_position(lttv_trace_get_traceset(self->trace));
90e19f82 1466
7a4bdb54
YB
1467#ifdef BABEL_CLEANUP
1468 nb_tracefile = self->parent.tracefiles->len;
90e19f82
AM
1469 for(i = 0 ; i < nb_tracefile ; i++) {
1470 tfcs =
1471 LTTV_TRACEFILE_STATE(g_array_index(self->parent.tracefiles,
1472 LttvTracefileContext*, i));
1473 tracefile_tree = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
1474 value = lttv_attribute_add(tracefiles_tree, i,
1475 LTTV_GOBJECT);
1476 *(value.v_gobject) = (GObject *)tracefile_tree;
348c6ba8 1477#if 0
90e19f82
AM
1478 value = lttv_attribute_add(tracefile_tree, LTTV_STATE_PROCESS,
1479 LTTV_UINT);
1480 *(value.v_uint) = tfcs->process->pid;
348c6ba8 1481#endif //0
90e19f82
AM
1482 value = lttv_attribute_add(tracefile_tree, LTTV_STATE_EVENT,
1483 LTTV_POINTER);
1484 /* Only save the position if the tfs has not infinite time. */
1485 //if(!g_tree_lookup(self->parent.ts_context->pqueue, &tfcs->parent)
1486 // && current_tfcs != tfcs) {
1487 if(ltt_time_compare(tfcs->parent.timestamp, ltt_time_infinite) == 0) {
1488 *(value.v_pointer) = NULL;
1489 } else {
1490 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.tf);
1491 ep = ltt_event_position_new();
1492 ltt_event_position(e, ep);
1493 *(value.v_pointer) = ep;
1494
1495 guint nb_block, offset;
1496 guint64 tsc;
1497 LttTracefile *tf;
1498 ltt_event_position_get(ep, &tf, &nb_block, &offset, &tsc);
1499 g_info("Block %u offset %u tsc %" PRIu64 " time %lu.%lu", nb_block,
1500 offset, tsc, tfcs->parent.timestamp.tv_sec,
1501 tfcs->parent.timestamp.tv_nsec);
1502 }
1503 }
7a4bdb54 1504#endif /* BABEL_CLEANUP */
90e19f82
AM
1505
1506 /* save the cpu state */
1507 {
1508 value = lttv_attribute_add(container, LTTV_STATE_RESOURCE_CPUS_COUNT,
1509 LTTV_UINT);
1510 *(value.v_uint) = nb_cpus;
1511
1512 value = lttv_attribute_add(container, LTTV_STATE_RESOURCE_CPUS,
1513 LTTV_POINTER);
1514 *(value.v_pointer) = lttv_state_copy_cpu_states(self->cpu_states, nb_cpus);
1515 }
1516
1517 /* save the irq state */
1518 nb_irqs = self->name_tables->nb_irqs;
1519 {
1520 value = lttv_attribute_add(container, LTTV_STATE_RESOURCE_IRQS,
1521 LTTV_POINTER);
1522 *(value.v_pointer) = lttv_state_copy_irq_states(self->irq_states, nb_irqs);
1523 }
1524
1525 /* save the soft irq state */
1526 nb_soft_irqs = self->name_tables->nb_soft_irqs;
1527 {
1528 value = lttv_attribute_add(container, LTTV_STATE_RESOURCE_SOFT_IRQS,
1529 LTTV_POINTER);
1530 *(value.v_pointer) = lttv_state_copy_soft_irq_states(self->soft_irq_states, nb_soft_irqs);
1531 }
1532
1533 /* save the trap state */
1534 nb_traps = self->name_tables->nb_traps;
1535 {
1536 value = lttv_attribute_add(container, LTTV_STATE_RESOURCE_TRAPS,
1537 LTTV_POINTER);
1538 *(value.v_pointer) = lttv_state_copy_trap_states(self->trap_states, nb_traps);
1539 }
1540
1541 /* save the blkdev states */
1542 value = lttv_attribute_add(container, LTTV_STATE_RESOURCE_BLKDEVS,
1543 LTTV_POINTER);
1544 *(value.v_pointer) = lttv_state_copy_blkdev_hashtable(self->bdev_states);
dc877563 1545}
1546
7a4bdb54 1547void lttv_state_restore(LttvTraceState *self, LttvAttribute *container)
dc877563 1548{
7a4bdb54 1549 guint i, pid, nb_cpus, nb_irqs, nb_soft_irqs, nb_traps;
90e19f82 1550 guint *running_process;
90e19f82 1551 LttvAttributeType type;
90e19f82 1552 LttvAttributeValue value;
dc877563 1553
90e19f82
AM
1554 type = lttv_attribute_get_by_name(container, LTTV_STATE_PROCESSES,
1555 &value);
1556 g_assert(type == LTTV_POINTER);
1557 lttv_state_free_process_table(self->processes);
1558 self->processes = lttv_state_copy_process_table(*(value.v_pointer));
308711e5 1559
90e19f82 1560 /* Add the currently running processes array */
7a4bdb54 1561 nb_cpus = lttv_trace_get_num_cpu(self->trace);
90e19f82
AM
1562 type = lttv_attribute_get_by_name(container, LTTV_STATE_RUNNING_PROCESS,
1563 &value);
1564 g_assert(type == LTTV_POINTER);
1565 running_process = *(value.v_pointer);
1566 for(i=0;i<nb_cpus;i++) {
1567 pid = running_process[i];
1568 self->running_process[i] = lttv_state_find_process(self, i, pid);
1569 g_assert(self->running_process[i] != NULL);
1570 }
348c6ba8 1571
7a4bdb54 1572 //nb_tracefile = self->parent.tracefiles->len;
308711e5 1573
90e19f82
AM
1574 //g_tree_destroy(tsc->pqueue);
1575 //tsc->pqueue = g_tree_new(compare_tracefile);
fbfbd4db 1576
90e19f82
AM
1577 /* restore cpu resource states */
1578 type = lttv_attribute_get_by_name(container, LTTV_STATE_RESOURCE_CPUS, &value);
1579 g_assert(type == LTTV_POINTER);
1580 lttv_state_free_cpu_states(self->cpu_states, nb_cpus);
1581 self->cpu_states = lttv_state_copy_cpu_states(*(value.v_pointer), nb_cpus);
e7f5e89d 1582
90e19f82
AM
1583 /* restore irq resource states */
1584 nb_irqs = self->name_tables->nb_irqs;
1585 type = lttv_attribute_get_by_name(container, LTTV_STATE_RESOURCE_IRQS, &value);
1586 g_assert(type == LTTV_POINTER);
1587 lttv_state_free_irq_states(self->irq_states, nb_irqs);
1588 self->irq_states = lttv_state_copy_irq_states(*(value.v_pointer), nb_irqs);
fc6a87b2 1589
90e19f82
AM
1590 /* restore soft irq resource states */
1591 nb_soft_irqs = self->name_tables->nb_soft_irqs;
1592 type = lttv_attribute_get_by_name(container, LTTV_STATE_RESOURCE_SOFT_IRQS, &value);
1593 g_assert(type == LTTV_POINTER);
1594 lttv_state_free_soft_irq_states(self->soft_irq_states, nb_soft_irqs);
1595 self->soft_irq_states = lttv_state_copy_soft_irq_states(*(value.v_pointer), nb_soft_irqs);
0305fe77 1596
90e19f82
AM
1597 /* restore trap resource states */
1598 nb_traps = self->name_tables->nb_traps;
1599 type = lttv_attribute_get_by_name(container, LTTV_STATE_RESOURCE_TRAPS, &value);
1600 g_assert(type == LTTV_POINTER);
1601 lttv_state_free_trap_states(self->trap_states, nb_traps);
1602 self->trap_states = lttv_state_copy_trap_states(*(value.v_pointer), nb_traps);
38726a78 1603
90e19f82
AM
1604 /* restore the blkdev states */
1605 type = lttv_attribute_get_by_name(container, LTTV_STATE_RESOURCE_BLKDEVS, &value);
1606 g_assert(type == LTTV_POINTER);
1607 lttv_state_free_blkdev_hashtable(self->bdev_states);
1608 self->bdev_states = lttv_state_copy_blkdev_hashtable(*(value.v_pointer));
1609
7a4bdb54 1610#ifdef BABEL_CLEANUP
90e19f82
AM
1611 for(i = 0 ; i < nb_tracefile ; i++) {
1612 tfcs =
1613 LTTV_TRACEFILE_STATE(g_array_index(self->parent.tracefiles,
1614 LttvTracefileContext*, i));
1615 type = lttv_attribute_get(tracefiles_tree, i, &name, &value, &is_named);
1616 g_assert(type == LTTV_GOBJECT);
1617 tracefile_tree = *((LttvAttribute **)(value.v_gobject));
348c6ba8 1618#if 0
90e19f82
AM
1619 type = lttv_attribute_get_by_name(tracefile_tree, LTTV_STATE_PROCESS,
1620 &value);
1621 g_assert(type == LTTV_UINT);
1622 pid = *(value.v_uint);
1623 tfcs->process = lttv_state_find_process_or_create(tfcs, pid);
348c6ba8 1624#endif //0
90e19f82
AM
1625 type = lttv_attribute_get_by_name(tracefile_tree, LTTV_STATE_EVENT,
1626 &value);
1627 g_assert(type == LTTV_POINTER);
1628 //g_assert(*(value.v_pointer) != NULL);
1629 ep = *(value.v_pointer);
1630 g_assert(tfcs->parent.t_context != NULL);
1631
1632 tfcs->cpu_state = &self->cpu_states[tfcs->cpu];
1633
1634 LttvTracefileContext *tfc = LTTV_TRACEFILE_CONTEXT(tfcs);
1635 g_tree_remove(tsc->pqueue, tfc);
1636
1637 if(ep != NULL) {
1638 retval= ltt_tracefile_seek_position(tfc->tf, ep);
1639 g_assert_cmpint(retval, ==, 0);
1640 tfc->timestamp = ltt_event_time(ltt_tracefile_get_event(tfc->tf));
1641 g_assert_cmpint(ltt_time_compare(tfc->timestamp, ltt_time_infinite),
1642 !=, 0);
1643 g_tree_insert(tsc->pqueue, tfc, tfc);
1644 g_info("Restoring state for a tf at time %lu.%lu",
1645 tfc->timestamp.tv_sec, tfc->timestamp.tv_nsec);
1646 } else {
1647 tfc->timestamp = ltt_time_infinite;
1648 }
1649 }
7a4bdb54 1650#endif /* BABEL_CLEANUP */
dc877563 1651}
1652
7a4bdb54
YB
1653/*
1654 * Note: the position must be explicitely set on the entire traceset to
1655 * match the trace states.
1656 */
1657LttvTracesetPosition *lttv_trace_state_get_position(LttvAttribute *container)
dc877563 1658{
7a4bdb54
YB
1659 LttvAttributeType type;
1660 LttvAttributeValue value;
dc877563 1661
7a4bdb54
YB
1662 type = lttv_attribute_get_by_name(container, LTTV_STATE_POSITION, &value);
1663 g_assert(type == LTTV_POINTER);
1664 return *(value.v_pointer);
1665}
dc877563 1666
7a4bdb54
YB
1667void lttv_state_saved_free(LttvTraceState *self, LttvAttribute *container)
1668{
1669 guint nb_cpus, nb_irqs, nb_soft_irqs;
90e19f82 1670 guint *running_process;
90e19f82 1671 LttvAttributeType type;
90e19f82 1672 LttvAttributeValue value;
dc877563 1673
90e19f82
AM
1674 type = lttv_attribute_get_by_name(container, LTTV_STATE_PROCESSES,
1675 &value);
1676 g_assert(type == LTTV_POINTER);
1677 lttv_state_free_process_table(*(value.v_pointer));
1678 *(value.v_pointer) = NULL;
1679 lttv_attribute_remove_by_name(container, LTTV_STATE_PROCESSES);
308711e5 1680
90e19f82
AM
1681 /* Free running processes array */
1682 type = lttv_attribute_get_by_name(container, LTTV_STATE_RUNNING_PROCESS,
1683 &value);
1684 g_assert(type == LTTV_POINTER);
1685 running_process = *(value.v_pointer);
1686 g_free(running_process);
348c6ba8 1687
58b4e4ae 1688 /* free cpu resources */
90e19f82
AM
1689 type = lttv_attribute_get_by_name(container, LTTV_STATE_RESOURCE_CPUS_COUNT, &value);
1690 g_assert(type == LTTV_UINT);
1691 nb_cpus = *value.v_uint;
1692 type = lttv_attribute_get_by_name(container, LTTV_STATE_RESOURCE_CPUS, &value);
1693 g_assert(type == LTTV_POINTER);
1694 lttv_state_free_cpu_states(*(value.v_pointer), nb_cpus);
bfe9b131 1695
90e19f82
AM
1696 /* free irq resource states */
1697 nb_irqs = self->name_tables->nb_irqs;
1698 type = lttv_attribute_get_by_name(container, LTTV_STATE_RESOURCE_IRQS, &value);
1699 g_assert(type == LTTV_POINTER);
1700 lttv_state_free_irq_states(*(value.v_pointer), nb_irqs);
bfe9b131 1701
90e19f82
AM
1702 /* free softirq resource states */
1703 nb_soft_irqs = self->name_tables->nb_soft_irqs;
1704 type = lttv_attribute_get_by_name(container, LTTV_STATE_RESOURCE_SOFT_IRQS, &value);
1705 g_assert(type == LTTV_POINTER);
1706 lttv_state_free_soft_irq_states(*(value.v_pointer), nb_soft_irqs);
227c6dfc 1707
90e19f82
AM
1708 /* free the blkdev states */
1709 type = lttv_attribute_get_by_name(container, LTTV_STATE_RESOURCE_BLKDEVS, &value);
1710 g_assert(type == LTTV_POINTER);
1711 lttv_state_free_blkdev_hashtable(*(value.v_pointer));
bfe9b131 1712
7a4bdb54
YB
1713 /* remove the position */
1714 type = lttv_attribute_get_by_name(container, LTTV_STATE_POSITION, &value);
1715 g_assert(type == LTTV_POINTER);
1716 lttv_traceset_destroy_position(*(value.v_pointer));
1717
1718#ifdef BABEL_CLEANUP
90e19f82 1719 nb_tracefile = self->parent.tracefiles->len;
308711e5 1720
90e19f82 1721 for(i = 0 ; i < nb_tracefile ; i++) {
e865422c 1722
90e19f82
AM
1723 type = lttv_attribute_get(tracefiles_tree, i, &name, &value, &is_named);
1724 g_assert(type == LTTV_GOBJECT);
1725 tracefile_tree = *((LttvAttribute **)(value.v_gobject));
308711e5 1726
90e19f82
AM
1727 type = lttv_attribute_get_by_name(tracefile_tree, LTTV_STATE_EVENT,
1728 &value);
1729 g_assert(type == LTTV_POINTER);
1730 if(*(value.v_pointer) != NULL) g_free(*(value.v_pointer));
1731 }
1732 g_object_unref(G_OBJECT(tracefiles_tree));
7a4bdb54 1733#endif /* BABEL_CLEANUP */
dc877563 1734}
1735
1736
f95bc830 1737static void free_saved_state(LttvTraceState *self)
1738{
90e19f82 1739 guint i, nb;
90e19f82 1740 LttvAttributeType type;
90e19f82 1741 LttvAttributeValue value;
90e19f82 1742 LttvAttributeName name;
90e19f82 1743 gboolean is_named;
90e19f82 1744 LttvAttribute *saved_states;
f95bc830 1745
7a4bdb54 1746 saved_states = lttv_attribute_find_subdir(lttv_trace_attribute(self->trace),
90e19f82 1747 LTTV_STATE_SAVED_STATES);
f95bc830 1748
90e19f82
AM
1749 nb = lttv_attribute_get_number(saved_states);
1750 for(i = 0 ; i < nb ; i++) {
1751 type = lttv_attribute_get(saved_states, i, &name, &value, &is_named);
1752 g_assert(type == LTTV_GOBJECT);
7a4bdb54 1753 lttv_state_saved_free(self, *((LttvAttribute **)value.v_gobject));
90e19f82 1754 }
f95bc830 1755
7a4bdb54
YB
1756 lttv_attribute_remove_by_name(lttv_trace_attribute(self->trace),
1757 LTTV_STATE_SAVED_STATES);
f95bc830 1758}
1759
1760
7a4bdb54 1761static void create_max_time(LttvTraceState *trace_state)
f95bc830 1762{
90e19f82 1763 LttvAttributeValue v;
f95bc830 1764
7a4bdb54
YB
1765 lttv_attribute_find(lttv_trace_attribute(trace_state->trace),
1766 LTTV_STATE_SAVED_STATES_TIME,
90e19f82
AM
1767 LTTV_POINTER, &v);
1768 g_assert(*(v.v_pointer) == NULL);
1769 *(v.v_pointer) = g_new(LttTime,1);
1770 *((LttTime *)*(v.v_pointer)) = ltt_time_zero;
f95bc830 1771}
1772
1773
7a4bdb54 1774static void get_max_time(LttvTraceState *trace_state)
f95bc830 1775{
90e19f82 1776 LttvAttributeValue v;
f95bc830 1777
7a4bdb54
YB
1778 lttv_attribute_find(lttv_trace_attribute(trace_state->trace),
1779 LTTV_STATE_SAVED_STATES_TIME,
90e19f82
AM
1780 LTTV_POINTER, &v);
1781 g_assert(*(v.v_pointer) != NULL);
7a4bdb54 1782 trace_state->max_time_state_recomputed_in_seek = (LttTime *)*(v.v_pointer);
f95bc830 1783}
1784
1785
7a4bdb54 1786static void free_max_time(LttvTraceState *trace_state)
f95bc830 1787{
90e19f82 1788 LttvAttributeValue v;
f95bc830 1789
7a4bdb54
YB
1790 lttv_attribute_find(lttv_trace_attribute(trace_state->trace),
1791 LTTV_STATE_SAVED_STATES_TIME,
90e19f82
AM
1792 LTTV_POINTER, &v);
1793 g_free(*(v.v_pointer));
1794 *(v.v_pointer) = NULL;
f95bc830 1795}
1796
90e19f82 1797static void create_name_tables(LttvTraceState *tcs)
b445142a 1798{
90e19f82
AM
1799 int i;
1800
1801 GString *fe_name = g_string_new("");
dc877563 1802
90e19f82 1803 LttvNameTables *name_tables = g_new(LttvNameTables, 1);
b445142a 1804
90e19f82 1805 LttvAttributeValue v;
f95bc830 1806
7a4bdb54 1807 // GArray *hooks;
f95bc830 1808
7a4bdb54 1809 lttv_attribute_find(lttv_trace_attribute(tcs->trace), LTTV_STATE_NAME_TABLES,
90e19f82
AM
1810 LTTV_POINTER, &v);
1811 g_assert(*(v.v_pointer) == NULL);
1812 *(v.v_pointer) = name_tables;
6418800d 1813
7a4bdb54 1814#ifdef BABEL_CLEANUP
90e19f82 1815 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 1);
e1de4b54 1816
90e19f82
AM
1817 if(!lttv_trace_find_hook(tcs->parent.t,
1818 LTT_CHANNEL_KERNEL,
1819 LTT_EVENT_SYSCALL_ENTRY,
1820 FIELD_ARRAY(LTT_FIELD_SYSCALL_ID),
1821 NULL, NULL, &hooks)) {
6418800d 1822
90e19f82 1823// th = lttv_trace_hook_get_first(&th);
8979f265 1824//
90e19f82
AM
1825// t = ltt_field_type(lttv_trace_get_hook_field(th, 0));
1826// nb = ltt_type_element_number(t);
8979f265 1827//
90e19f82
AM
1828// name_tables->syscall_names = g_new(GQuark, nb);
1829// name_tables->nb_syscalls = nb;
8979f265 1830//
90e19f82
AM
1831// for(i = 0 ; i < nb ; i++) {
1832// name_tables->syscall_names[i] = ltt_enum_string_get(t, i);
1833// if(!name_tables->syscall_names[i]) {
1834// GString *string = g_string_new("");
1835// g_string_printf(string, "syscall %u", i);
1836// name_tables->syscall_names[i] = g_quark_from_string(string->str);
1837// g_string_free(string, TRUE);
1838// }
1839// }
7a4bdb54 1840#endif /* BABEL_CLEANUP */
90e19f82 1841
df6c9904
MD
1842 name_tables->nb_syscalls = PREALLOC_NB_SYSCALLS;
1843 name_tables->syscall_names = g_new(GQuark, name_tables->nb_syscalls);
1844 for(i = 0 ; i < name_tables->nb_syscalls; i++) {
90e19f82
AM
1845 g_string_printf(fe_name, "syscall %d", i);
1846 name_tables->syscall_names[i] = g_quark_from_string(fe_name->str);
1847 }
7a4bdb54 1848#ifdef BABEL_CLEANUP
90e19f82
AM
1849 } else {
1850 name_tables->syscall_names = NULL;
1851 name_tables->nb_syscalls = 0;
1852 }
1853 lttv_trace_hook_remove_all(&hooks);
7a4bdb54 1854#endif /* BABEL_CLEANUP */
90e19f82 1855
7a4bdb54 1856#ifdef BABEL_CLEANUP
90e19f82
AM
1857 if(!lttv_trace_find_hook(tcs->parent.t,
1858 LTT_CHANNEL_KERNEL,
1859 LTT_EVENT_TRAP_ENTRY,
1860 FIELD_ARRAY(LTT_FIELD_TRAP_ID),
1861 NULL, NULL, &hooks) ||
1862 !lttv_trace_find_hook(tcs->parent.t,
1863 LTT_CHANNEL_KERNEL,
1864 LTT_EVENT_PAGE_FAULT_ENTRY,
1865 FIELD_ARRAY(LTT_FIELD_TRAP_ID),
1866 NULL, NULL, &hooks)) {
1867
1868// th = lttv_trace_hook_get_first(&th);
1869//
1870// t = ltt_field_type(lttv_trace_get_hook_field(th, 0));
1871// //nb = ltt_type_element_number(t);
1872//
1873// name_tables->trap_names = g_new(GQuark, nb);
1874// for(i = 0 ; i < nb ; i++) {
1875// name_tables->trap_names[i] = g_quark_from_string(
1876// ltt_enum_string_get(t, i));
1877// }
1878
7a4bdb54 1879#endif /* BABEL_CLEANUP */
df6c9904
MD
1880 name_tables->nb_traps = PREALLOC_NB_TRAPS;
1881 name_tables->trap_names = g_new(GQuark, name_tables->nb_traps);
1882 for(i = 0 ; i < name_tables->nb_traps; i++) {
90e19f82
AM
1883 g_string_printf(fe_name, "trap %d", i);
1884 name_tables->trap_names[i] = g_quark_from_string(fe_name->str);
1885 }
7a4bdb54 1886#ifdef BABEL_CLEANUP
90e19f82
AM
1887 } else {
1888 name_tables->trap_names = NULL;
1889 name_tables->nb_traps = 0;
1890 }
1891 lttv_trace_hook_remove_all(&hooks);
7a4bdb54 1892#endif /* BABEL_CLEANUP */
90e19f82 1893
7a4bdb54 1894#ifdef BABEL_CLEANUP
90e19f82
AM
1895 if(!lttv_trace_find_hook(tcs->parent.t,
1896 LTT_CHANNEL_KERNEL,
1897 LTT_EVENT_IRQ_ENTRY,
1898 FIELD_ARRAY(LTT_FIELD_IRQ_ID),
1899 NULL, NULL, &hooks)) {
1900
1901 /*
1902 name_tables->irq_names = g_new(GQuark, nb);
1903 for(i = 0 ; i < nb ; i++) {
1904 name_tables->irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
1905 }
1906 */
1907 /* FIXME: LttvIRQState *irq_states should become a g_array */
90e19f82 1908
7a4bdb54 1909#endif /* BABEL_CLEANUP */
df6c9904
MD
1910 name_tables->nb_irqs = PREALLOC_NB_IRQS;
1911 name_tables->irq_names = g_new(GQuark, name_tables->nb_irqs);
1912 for(i = 0 ; i < name_tables->nb_irqs; i++) {
90e19f82
AM
1913 g_string_printf(fe_name, "irq %d", i);
1914 name_tables->irq_names[i] = g_quark_from_string(fe_name->str);
1915 }
7a4bdb54 1916#ifdef BABEL_CLEANUP
90e19f82
AM
1917 } else {
1918 name_tables->nb_irqs = 0;
1919 name_tables->irq_names = NULL;
1920 }
1921 lttv_trace_hook_remove_all(&hooks);
7a4bdb54 1922#endif /* BABEL_CLEANUP */
90e19f82
AM
1923 /*
1924 name_tables->soft_irq_names = g_new(GQuark, nb);
1925 for(i = 0 ; i < nb ; i++) {
1926 name_tables->soft_irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
1927 }
1928 */
1929
df6c9904 1930 name_tables->nb_soft_irqs = PREALLOC_NB_SOFT_IRQS;
90e19f82
AM
1931 name_tables->soft_irq_names = g_new(GQuark, name_tables->nb_soft_irqs);
1932 for(i = 0 ; i < name_tables->nb_soft_irqs ; i++) {
1933 g_string_printf(fe_name, "softirq %d", i);
1934 name_tables->soft_irq_names[i] = g_quark_from_string(fe_name->str);
1935 }
7a4bdb54 1936 // g_array_free(hooks, TRUE);
90e19f82
AM
1937
1938 g_string_free(fe_name, TRUE);
2d0d580c 1939
e9a5b514 1940#if (__WORDSIZE == 32)
90e19f82
AM
1941 name_tables->kprobe_hash = g_hash_table_new_full(guint64_hash, guint64_equal,
1942 g_free, NULL);
9ee1ff6a 1943#else
90e19f82 1944 name_tables->kprobe_hash = g_hash_table_new(g_direct_hash, g_direct_equal);
9ee1ff6a 1945#endif
b445142a 1946}
1947
1948
90e19f82 1949static void get_name_tables(LttvTraceState *tcs)
f95bc830 1950{
90e19f82 1951 LttvAttributeValue v;
f95bc830 1952
7a4bdb54 1953 lttv_attribute_find(lttv_trace_attribute(tcs->trace), LTTV_STATE_NAME_TABLES,
90e19f82
AM
1954 LTTV_POINTER, &v);
1955 g_assert(*(v.v_pointer) != NULL);
1956 tcs->name_tables = (LttvNameTables *)*(v.v_pointer);
f95bc830 1957}
1958
1959
90e19f82 1960static void free_name_tables(LttvTraceState *tcs)
b445142a 1961{
90e19f82 1962 LttvNameTables *name_tables;
f95bc830 1963
90e19f82 1964 LttvAttributeValue v;
f95bc830 1965
7a4bdb54 1966 lttv_attribute_find(lttv_trace_attribute(tcs->trace), LTTV_STATE_NAME_TABLES,
90e19f82
AM
1967 LTTV_POINTER, &v);
1968 name_tables = (LttvNameTables *)*(v.v_pointer);
1969 *(v.v_pointer) = NULL;
f95bc830 1970
eed2ef37 1971 // g_free(name_tables->eventtype_names);
90e19f82
AM
1972 if(name_tables->syscall_names) g_free(name_tables->syscall_names);
1973 if(name_tables->trap_names) g_free(name_tables->trap_names);
1974 if(name_tables->irq_names) g_free(name_tables->irq_names);
1975 if(name_tables->soft_irq_names) g_free(name_tables->soft_irq_names);
1976 g_hash_table_destroy(name_tables->kprobe_hash);
1977 g_free(name_tables);
b445142a 1978}
dc877563 1979
15b3d537 1980#ifdef HASH_TABLE_DEBUG
1981
1982static void test_process(gpointer key, gpointer value, gpointer user_data)
1983{
90e19f82
AM
1984 LttvProcessState *process = (LttvProcessState *)value;
1985
1986 /* Test for process corruption */
1987 guint stack_len = process->execution_stack->len;
15b3d537 1988}
1989
1990static void hash_table_check(GHashTable *table)
1991{
90e19f82 1992 g_hash_table_foreach(table, test_process, NULL);
15b3d537 1993}
1994
1995
1996#endif
1997
d3d99fde 1998/* clears the stack and sets the state passed as argument */
1999static void cpu_set_base_mode(LttvCPUState *cpust, LttvCPUMode state)
2000{
90e19f82
AM
2001 g_array_set_size(cpust->mode_stack, 1);
2002 ((GQuark *)cpust->mode_stack->data)[0] = state;
d3d99fde 2003}
2004
2005static void cpu_push_mode(LttvCPUState *cpust, LttvCPUMode state)
2006{
90e19f82
AM
2007 g_array_set_size(cpust->mode_stack, cpust->mode_stack->len + 1);
2008 ((GQuark *)cpust->mode_stack->data)[cpust->mode_stack->len - 1] = state;
d3d99fde 2009}
2010
2011static void cpu_pop_mode(LttvCPUState *cpust)
2012{
90e19f82
AM
2013 if(cpust->mode_stack->len <= 1)
2014 cpu_set_base_mode(cpust, LTTV_CPU_UNKNOWN);
2015 else
2016 g_array_set_size(cpust->mode_stack, cpust->mode_stack->len - 1);
d3d99fde 2017}
15b3d537 2018
5e563da0 2019/* clears the stack and sets the state passed as argument */
27811799 2020static void bdev_set_base_mode(LttvBdevState *bdevst, LttvBdevMode state)
2021{
90e19f82
AM
2022 g_array_set_size(bdevst->mode_stack, 1);
2023 ((GQuark *)bdevst->mode_stack->data)[0] = state;
27811799 2024}
2025
2026static void bdev_push_mode(LttvBdevState *bdevst, LttvBdevMode state)
2027{
90e19f82
AM
2028 g_array_set_size(bdevst->mode_stack, bdevst->mode_stack->len + 1);
2029 ((GQuark *)bdevst->mode_stack->data)[bdevst->mode_stack->len - 1] = state;
27811799 2030}
2031
2032static void bdev_pop_mode(LttvBdevState *bdevst)
2033{
90e19f82
AM
2034 if(bdevst->mode_stack->len <= 1)
2035 bdev_set_base_mode(bdevst, LTTV_BDEV_UNKNOWN);
2036 else
2037 g_array_set_size(bdevst->mode_stack, bdevst->mode_stack->len - 1);
27811799 2038}
2039
5e563da0 2040static void irq_set_base_mode(LttvIRQState *irqst, LttvIRQMode state)
2041{
90e19f82
AM
2042 g_array_set_size(irqst->mode_stack, 1);
2043 ((GQuark *)irqst->mode_stack->data)[0] = state;
5e563da0 2044}
2045
2046static void irq_push_mode(LttvIRQState *irqst, LttvIRQMode state)
2047{
90e19f82
AM
2048 g_array_set_size(irqst->mode_stack, irqst->mode_stack->len + 1);
2049 ((GQuark *)irqst->mode_stack->data)[irqst->mode_stack->len - 1] = state;
5e563da0 2050}
2051
2052static void irq_pop_mode(LttvIRQState *irqst)
2053{
90e19f82
AM
2054 if(irqst->mode_stack->len <= 1)
2055 irq_set_base_mode(irqst, LTTV_IRQ_UNKNOWN);
2056 else
2057 g_array_set_size(irqst->mode_stack, irqst->mode_stack->len - 1);
5e563da0 2058}
2059
7a4bdb54
YB
2060static void push_state(LttvEvent *event,
2061 LttvTraceState *ts, LttvExecutionMode t,
90e19f82 2062 guint state_id)
dc877563 2063{
90e19f82 2064 LttvExecutionState *es;
7a4bdb54 2065 gint cpu;
90e19f82 2066
7a4bdb54
YB
2067 cpu = lttv_traceset_get_cpuid_from_event(event);
2068 g_assert(cpu >= 0);
15b3d537 2069
2070#ifdef HASH_TABLE_DEBUG
90e19f82 2071 hash_table_check(ts->processes);
15b3d537 2072#endif
90e19f82 2073 LttvProcessState *process = ts->running_process[cpu];
dc877563 2074
90e19f82 2075 guint depth = process->execution_stack->len;
dc877563 2076
90e19f82
AM
2077 process->execution_stack =
2078 g_array_set_size(process->execution_stack, depth + 1);
2079 /* Keep in sync */
2080 process->state =
2081 &g_array_index(process->execution_stack, LttvExecutionState, depth - 1);
2082
2083 es = &g_array_index(process->execution_stack, LttvExecutionState, depth);
2084 es->t = t;
2085 es->n = state_id;
7a4bdb54 2086 es->entry = es->change = lttv_event_get_timestamp(event);
90e19f82
AM
2087 es->cum_cpu_time = ltt_time_zero;
2088 es->s = process->state->s;
2089 process->state = es;
dc877563 2090}
2091
b49e54b4 2092/* pop state
2093 * return 1 when empty, else 0 */
90e19f82 2094int
7a4bdb54 2095lttv_state_pop_state_cleanup(LttvProcessState *process, LttvEvent *event)
b49e54b4 2096{
90e19f82 2097 guint depth = process->execution_stack->len;
b49e54b4 2098
90e19f82
AM
2099 if(depth == 1){
2100 return 1;
2101 }
b49e54b4 2102
90e19f82
AM
2103 process->execution_stack =
2104 g_array_set_size(process->execution_stack, depth - 1);
2105 process->state = &g_array_index(process->execution_stack, LttvExecutionState,
2106 depth - 2);
7a4bdb54 2107 process->state->change = lttv_event_get_timestamp(event);
90e19f82
AM
2108
2109 return 0;
b49e54b4 2110}
dc877563 2111
7a4bdb54
YB
2112static void pop_state(LttvEvent *event,
2113 LttvTraceState *ts, LttvExecutionMode t)
dc877563 2114{
7a4bdb54
YB
2115 LttvProcessState *process;
2116 gint cpu;
2117
2118 cpu = lttv_traceset_get_cpuid_from_event(event);
2119 g_assert(cpu >= 0);
2120 process = ts->running_process[cpu];
90e19f82
AM
2121
2122 guint depth = process->execution_stack->len;
2123
2124 if(process->state->t != t){
7a4bdb54
YB
2125 g_info("Different execution mode type: ignore it\n"
2126 );
2127
90e19f82
AM
2128 g_info("process state has %s when pop_int is %s\n",
2129 g_quark_to_string(process->state->t),
2130 g_quark_to_string(t));
2131 g_info("{ %u, %u, %s, %s, %s }\n",
2132 process->pid,
2133 process->ppid,
2134 g_quark_to_string(process->name),
2135 g_quark_to_string(process->brand),
2136 g_quark_to_string(process->state->s));
2137 return;
2138 }
2139
2140 if(depth == 1){
7a4bdb54
YB
2141 //TODO ybrosseau readd debug
2142 //g_info("Trying to pop last state on stack (%lu.%09lu): ignore it\n",
2143 // tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec);
2144 g_info("Trying to pop last state on stack: ignore it\n");
90e19f82
AM
2145 return;
2146 }
2147
2148 process->execution_stack =
2149 g_array_set_size(process->execution_stack, depth - 1);
2150 process->state = &g_array_index(process->execution_stack, LttvExecutionState,
2151 depth - 2);
7a4bdb54 2152 process->state->change = lttv_event_get_timestamp(event);
dc877563 2153}
2154
6806b3c6 2155struct search_result {
90e19f82
AM
2156 const LttTime *time; /* Requested time */
2157 LttTime *best; /* Best result */
6806b3c6 2158};
2159
8c108c1c 2160/* Return a new and initialized LttvProcessState structure */
dc877563 2161
90e19f82
AM
2162LttvProcessState *lttv_state_create_process(LttvTraceState *tcs,
2163 LttvProcessState *parent, guint cpu, guint pid,
2164 guint tgid, GQuark name, const LttTime *timestamp)
2165{
2166 LttvProcessState *process = g_new(LttvProcessState, 1);
2167
2168 LttvExecutionState *es;
2169
2170 char buffer[128];
2171
2172 process->pid = pid;
2173 process->tgid = tgid;
2174 process->cpu = cpu;
2175 process->name = name;
2176 process->brand = LTTV_STATE_UNBRANDED;
2177 //process->last_cpu = tfs->cpu_name;
2178 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
2179 process->type = LTTV_STATE_USER_THREAD;
90e19f82
AM
2180
2181 g_info("Process %u, core %p", process->pid, process);
2182 g_hash_table_insert(tcs->processes, process, process);
2183
2184 if(parent) {
2185 process->ppid = parent->pid;
2186 process->creation_time = *timestamp;
2187 }
2188
2189 /* No parent. This process exists but we are missing all information about
2190 its creation. The birth time is set to zero but we remember the time of
2191 insertion */
2192
2193 else {
2194 process->ppid = 0;
2195 process->creation_time = ltt_time_zero;
2196 }
2197
2198 process->insertion_time = *timestamp;
2199 sprintf(buffer,"%d-%lu.%lu",pid, process->creation_time.tv_sec,
2200 process->creation_time.tv_nsec);
2201 process->pid_time = g_quark_from_string(buffer);
2202 process->cpu = cpu;
2203 process->free_events = 0;
2204 //process->last_cpu = tfs->cpu_name;
2205 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
2206 process->execution_stack = g_array_sized_new(FALSE, FALSE,
2207 sizeof(LttvExecutionState), PREALLOCATED_EXECUTION_STACK);
2208 process->execution_stack = g_array_set_size(process->execution_stack, 2);
2209 es = process->state = &g_array_index(process->execution_stack,
2210 LttvExecutionState, 0);
2211 es->t = LTTV_STATE_USER_MODE;
2212 es->n = LTTV_STATE_SUBMODE_NONE;
2213 es->entry = *timestamp;
2214 //g_assert(timestamp->tv_sec != 0);
2215 es->change = *timestamp;
2216 es->cum_cpu_time = ltt_time_zero;
2217 es->s = LTTV_STATE_RUN;
2218
2219 es = process->state = &g_array_index(process->execution_stack,
2220 LttvExecutionState, 1);
2221 es->t = LTTV_STATE_SYSCALL;
2222 es->n = LTTV_STATE_SUBMODE_NONE;
2223 es->entry = *timestamp;
2224 //g_assert(timestamp->tv_sec != 0);
2225 es->change = *timestamp;
2226 es->cum_cpu_time = ltt_time_zero;
2227 es->s = LTTV_STATE_WAIT_FORK;
2228
2229 /* Allocate an empty function call stack. If it's empty, use 0x0. */
7a4bdb54
YB
2230#ifdef BABEL_CLEANUP
2231 //process->user_stack = g_array_sized_new(FALSE, FALSE,
2232 // sizeof(guint64), 0);
2233#endif
90e19f82
AM
2234 process->fds = g_hash_table_new(g_direct_hash, g_direct_equal);
2235
2236 return process;
dc877563 2237}
2238
2a2fa4f0 2239LttvProcessState *
90e19f82
AM
2240lttv_state_find_process(LttvTraceState *ts, guint cpu, guint pid)
2241{
2242 LttvProcessState key;
2243 LttvProcessState *process;
2244
2245 key.pid = pid;
2246 key.cpu = cpu;
2247 process = g_hash_table_lookup(ts->processes, &key);
2248 return process;
2249}
2250
2251LttvProcessState *lttv_state_find_process_or_create(LttvTraceState *ts,
2252 guint cpu, guint pid, const LttTime *timestamp)
2253{
2254 LttvProcessState *process = lttv_state_find_process(ts, cpu, pid);
2255 LttvExecutionState *es;
2256
2257 /* Put ltt_time_zero creation time for unexisting processes */
2258 if(unlikely(process == NULL)) {
2259 process = lttv_state_create_process(ts,
2260 NULL, cpu, pid, 0, LTTV_STATE_UNNAMED, timestamp);
2261 /* We are not sure is it's a kernel thread or normal thread, put the
2262 * bottom stack state to unknown */
2263 process->execution_stack =
2264 g_array_set_size(process->execution_stack, 1);
2265 process->state = es =
2266 &g_array_index(process->execution_stack, LttvExecutionState, 0);
2267 es->t = LTTV_STATE_MODE_UNKNOWN;
2268 es->s = LTTV_STATE_UNNAMED;
2269 }
2270 return process;
2a2fa4f0 2271}
2272
41c7f803 2273/* FIXME : this function should be called when we receive an event telling that
2274 * release_task has been called in the kernel. In happens generally when
8c108c1c 2275 * the parent waits for its child termination, but may also happens in special
41c7f803 2276 * cases in the child's exit : when the parent ignores its children SIGCCHLD or
2277 * has the flag SA_NOCLDWAIT. It can also happen when the child is part
5567bd2b 2278 * of a killed thread group, but isn't the leader.
41c7f803 2279 */
7a4bdb54 2280static int exit_process(LttvEvent *event, LttvProcessState *process)
dc877563 2281{
7a4bdb54 2282 LttvTraceState *ts = event->state;
90e19f82 2283 LttvProcessState key;
ba576a78 2284
90e19f82
AM
2285 /* Wait for both schedule with exit dead and process free to happen.
2286 * They can happen in any order. */
2287 if (++(process->free_events) < 2)
2288 return 0;
2fe13145 2289
90e19f82
AM
2290 key.pid = process->pid;
2291 key.cpu = process->cpu;
2292 g_hash_table_remove(ts->processes, &key);
2293 g_array_free(process->execution_stack, TRUE);
8c108c1c 2294
90e19f82
AM
2295 /* the following also clears the content */
2296 g_hash_table_destroy(process->fds);
8c108c1c 2297
90e19f82
AM
2298 g_free(process);
2299 return 1;
dc877563 2300}
2301
2302
b445142a 2303static void free_process_state(gpointer key, gpointer value,gpointer user_data)
dc877563 2304{
90e19f82 2305 g_array_free(((LttvProcessState *)value)->execution_stack, TRUE);
8c108c1c 2306
90e19f82
AM
2307 /* the following also clears the content */
2308 g_hash_table_destroy(((LttvProcessState *)value)->fds);
8c108c1c 2309
90e19f82 2310 g_free(value);
dc877563 2311}
2312
2313
308711e5 2314static void lttv_state_free_process_table(GHashTable *processes)
dc877563 2315{
90e19f82
AM
2316 g_hash_table_foreach(processes, free_process_state, NULL);
2317 g_hash_table_destroy(processes);
dc877563 2318}
2319
2320
b445142a 2321static gboolean syscall_entry(void *hook_data, void *call_data)
dc877563 2322{
7a4bdb54
YB
2323 LttvEvent *event;
2324 guint cpu;
2325 LttvTraceState *ts;
2326 LttvProcessState *process;
90e19f82 2327 LttvExecutionSubmode submode;
7a4bdb54
YB
2328 char syscall_name[200];
2329
2330 event = (LttvEvent *) call_data;
2331 if (strncmp(lttv_traceset_get_name_from_event(event),
2332 "sys_", sizeof("sys_") - 1) != 0)
2333 return FALSE;
b445142a 2334
7a4bdb54
YB
2335 strncpy(syscall_name,lttv_traceset_get_name_from_event(event)+4,200);
2336
2337 cpu = lttv_traceset_get_cpuid_from_event(event);
2338 ts = event->state;
2339 process = ts->running_process[cpu];
2340
2341 submode = g_quark_from_string(syscall_name);
90e19f82
AM
2342 /* There can be no system call from PID 0 : unknown state */
2343 if(process->pid != 0)
7a4bdb54 2344 push_state(event, ts, LTTV_STATE_SYSCALL, submode);
90e19f82 2345 return FALSE;
dc877563 2346}
2347
2348
b445142a 2349static gboolean syscall_exit(void *hook_data, void *call_data)
dc877563 2350{
7a4bdb54
YB
2351 LttvEvent *event;
2352 guint cpu;
2353 LttvTraceState *ts;
2354 LttvProcessState *process;
2355
2356
2357 event = (LttvEvent *) call_data;
2358 if (strcmp(lttv_traceset_get_name_from_event(event),
2359 "exit_syscall") != 0)
2360 return FALSE;
2361
2362 cpu = lttv_traceset_get_cpuid_from_event(event);
2363 ts = event->state;
2364 process = ts->running_process[cpu];
dc877563 2365
90e19f82 2366 /* There can be no system call from PID 0 : unknown state */
7a4bdb54
YB
2367 if (process->pid != 0)
2368 pop_state(event, ts, LTTV_STATE_SYSCALL);
90e19f82 2369 return FALSE;
dc877563 2370}
2371
7a4bdb54 2372#ifdef BABEL_CLEANUP
b445142a 2373static gboolean trap_entry(void *hook_data, void *call_data)
dc877563 2374{
90e19f82
AM
2375 LttvTracefileState *s = (LttvTracefileState *)call_data;
2376 LttvTraceState *ts = (LttvTraceState *)s->parent.t_context;
2377 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
2378 LttvTraceHook *th = (LttvTraceHook *)hook_data;
2379 struct marker_field *f = lttv_trace_get_hook_field(th, 0);
2380 LttvNameTables *nt = ((LttvTraceState *)(s->parent.t_context))->name_tables;
dc877563 2381
90e19f82 2382 LttvExecutionSubmode submode;
b445142a 2383
90e19f82 2384 guint64 trap = ltt_event_get_long_unsigned(e, f);
5e96e7e3 2385
90e19f82 2386 expand_trap_table(ts, trap);
b0e00636 2387
90e19f82 2388 submode = nt->trap_names[trap];
5e96e7e3 2389
90e19f82 2390 push_state(s, LTTV_STATE_TRAP, submode);
d3d99fde 2391
90e19f82
AM
2392 /* update cpu status */
2393 cpu_push_mode(s->cpu_state, LTTV_CPU_TRAP);
d3d99fde 2394
90e19f82
AM
2395 /* update trap status */
2396 g_array_append_val(s->cpu_state->trap_stack, trap);
2397 ts->trap_states[trap].running++;
a81d2a59 2398
90e19f82 2399 return FALSE;
dc877563 2400}
2401
b445142a 2402static gboolean trap_exit(void *hook_data, void *call_data)
dc877563 2403{
90e19f82
AM
2404 LttvTracefileState *s = (LttvTracefileState *)call_data;
2405 LttvTraceState *ts = (LttvTraceState *)s->parent.t_context;
dc877563 2406
90e19f82 2407 pop_state(s, LTTV_STATE_TRAP);
d3d99fde 2408
90e19f82
AM
2409 /* update cpu status */
2410 cpu_pop_mode(s->cpu_state);
d3d99fde 2411
90e19f82
AM
2412 /* update trap status */
2413 if (s->cpu_state->trap_stack->len > 0) {
2414 gint last = g_array_index(s->cpu_state->trap_stack, gint,
2415 s->cpu_state->trap_stack->len-1);
2416 if(ts->trap_states[last].running)
2417 ts->trap_states[last].running--;
2418 g_array_remove_index(s->cpu_state->trap_stack,
2419 s->cpu_state->trap_stack->len-1);
2420 }
2421 return FALSE;
dc877563 2422}
7a4bdb54 2423#endif /* BABEL_CLEANUP */
dc877563 2424
b445142a 2425static gboolean irq_entry(void *hook_data, void *call_data)
dc877563 2426{
7a4bdb54
YB
2427 LttvEvent *event;
2428 guint cpu;
2429 LttvTraceState *ts;
dc877563 2430
90e19f82 2431 LttvExecutionSubmode submode;
7a4bdb54
YB
2432 LttvNameTables *nt;
2433 guint64 irq;
2434
2435 event = (LttvEvent *) call_data;
2436 if (strcmp(lttv_traceset_get_name_from_event(event),
2437 "irq_handler_entry") != 0)
2438 return FALSE;
2439
2440 cpu = lttv_traceset_get_cpuid_from_event(event);
2441 ts = event->state;
2442
2443 nt = ts->name_tables;
fc26eb1b 2444 irq = lttv_event_get_long(event, "irq");
b445142a 2445
90e19f82 2446 expand_irq_table(ts, irq);
b0e00636 2447
90e19f82 2448 submode = nt->irq_names[irq];
b445142a 2449
90e19f82 2450 /* Do something with the info about being in user or system mode when int? */
7a4bdb54 2451 push_state(event, ts, LTTV_STATE_IRQ, submode);
598026ba 2452
90e19f82 2453 /* update cpu status */
7a4bdb54 2454 cpu_push_mode(&(ts->cpu_states[cpu]), LTTV_CPU_IRQ);
598026ba 2455
90e19f82 2456 /* update irq status */
7a4bdb54 2457 g_array_append_val(ts->cpu_states[cpu].irq_stack, irq);
90e19f82 2458 irq_push_mode(&ts->irq_states[irq], LTTV_IRQ_BUSY);
5e563da0 2459
90e19f82 2460 return FALSE;
dc877563 2461}
2462
302efbad 2463static gboolean soft_irq_exit(void *hook_data, void *call_data)
2464{
7a4bdb54
YB
2465 LttvEvent *event;
2466 guint cpu;
2467 LttvTraceState *ts;
302efbad 2468
7a4bdb54
YB
2469 LttvCPUState *cpu_state;
2470
2471 event = (LttvEvent *) call_data;
2472 if (strcmp(lttv_traceset_get_name_from_event(event),
2473 "softirq_exit") != 0)
2474 return FALSE;
2475
2476 cpu = lttv_traceset_get_cpuid_from_event(event);
2477 ts = event->state;
2478
2479 cpu_state = &(ts->cpu_states[cpu]);
2480 pop_state(event, ts, LTTV_STATE_SOFT_IRQ);
302efbad 2481
90e19f82 2482 /* update cpu status */
7a4bdb54 2483 cpu_pop_mode(cpu_state);
d34141ca 2484
90e19f82 2485 /* update softirq status */
7a4bdb54
YB
2486 if (cpu_state->softirq_stack->len > 0) {
2487 gint last = g_array_index(cpu_state->softirq_stack, gint, cpu_state->softirq_stack->len-1);
90e19f82
AM
2488 if(ts->soft_irq_states[last].running)
2489 ts->soft_irq_states[last].running--;
7a4bdb54 2490 g_array_remove_index(cpu_state->softirq_stack, cpu_state->softirq_stack->len-1);
90e19f82
AM
2491 }
2492 return FALSE;
0305fe77 2493}
dc877563 2494
b445142a 2495static gboolean irq_exit(void *hook_data, void *call_data)
dc877563 2496{
7a4bdb54
YB
2497 LttvEvent *event;
2498 guint cpu;
2499 LttvTraceState *ts;
2500
2501 LttvCPUState *cpu_state;
2502
2503 event = (LttvEvent *) call_data;
2504 if (strcmp(lttv_traceset_get_name_from_event(event),
2505 "irq_handler_exit") != 0)
2506 return FALSE;
dc877563 2507
7a4bdb54
YB
2508 cpu = lttv_traceset_get_cpuid_from_event(event);
2509 ts = event->state;
2510 cpu_state = &(ts->cpu_states[cpu]);
2511
2512 pop_state(event, ts, LTTV_STATE_IRQ);
598026ba 2513
90e19f82 2514 /* update cpu status */
7a4bdb54 2515 cpu_pop_mode(cpu_state);
598026ba 2516
90e19f82 2517 /* update irq status */
7a4bdb54
YB
2518 if (cpu_state->irq_stack->len > 0) {
2519 gint last = g_array_index(cpu_state->irq_stack, gint, cpu_state->irq_stack->len-1);
2520 g_array_remove_index(cpu_state->irq_stack, cpu_state->irq_stack->len-1);
90e19f82
AM
2521 irq_pop_mode(&ts->irq_states[last]);
2522 }
8743690d 2523
90e19f82 2524 return FALSE;
dc877563 2525}
2526
a970363f 2527static gboolean soft_irq_raise(void *hook_data, void *call_data)
2528{
7a4bdb54
YB
2529 LttvEvent *event;
2530 //guint cpu;
2531 LttvTraceState *ts;
2532
2533
2534 guint64 softirq;
2535 event = (LttvEvent *) call_data;
2536 if (strcmp(lttv_traceset_get_name_from_event(event),
2537 "softirq_raise") != 0)
2538 return FALSE;
e865422c 2539
7a4bdb54
YB
2540 //cpu = lttv_traceset_get_cpuid_from_event(event);
2541 ts = event->state;
2542 softirq = lttv_event_get_long_unsigned(event, "vec");
a970363f 2543
df6c9904
MD
2544 expand_soft_irq_table(ts, softirq);
2545
90e19f82
AM
2546 /* update softirq status */
2547 /* a soft irq raises are not cumulative */
2548 ts->soft_irq_states[softirq].pending=1;
a970363f 2549
90e19f82 2550 return FALSE;
a970363f 2551}
2552
faf074a3 2553static gboolean soft_irq_entry(void *hook_data, void *call_data)
2554{
7a4bdb54
YB
2555 LttvEvent *event;
2556 guint cpu;
2557 LttvTraceState *ts;
90e19f82 2558 LttvExecutionSubmode submode;
7a4bdb54
YB
2559 LttvNameTables *nt;
2560 guint64 softirq;
2561
2562 event = (LttvEvent *) call_data;
2563 if (strcmp(lttv_traceset_get_name_from_event(event),
b68bfc99 2564 "softirq_entry") != 0)
7a4bdb54
YB
2565 return FALSE;
2566
2567 cpu = lttv_traceset_get_cpuid_from_event(event);
2568 ts = event->state;
2569
2570
2571
2572
2573 softirq = lttv_event_get_long_unsigned(event, "vec");
90e19f82 2574 expand_soft_irq_table(ts, softirq);
7a4bdb54 2575 nt = ts->name_tables;
90e19f82 2576 submode = nt->soft_irq_names[softirq];
faf074a3 2577
90e19f82 2578 /* Do something with the info about being in user or system mode when int? */
7a4bdb54 2579 push_state(event, ts, LTTV_STATE_SOFT_IRQ, submode);
0305fe77 2580
90e19f82 2581 /* update cpu status */
7a4bdb54 2582 cpu_push_mode(&(ts->cpu_states[cpu]), LTTV_CPU_SOFT_IRQ);
d34141ca 2583
90e19f82 2584 /* update softirq status */
7a4bdb54
YB
2585 g_array_append_val(ts->cpu_states[cpu].softirq_stack, softirq);
2586 if (ts->soft_irq_states[softirq].pending)
90e19f82
AM
2587 ts->soft_irq_states[softirq].pending--;
2588 ts->soft_irq_states[softirq].running++;
0305fe77 2589
90e19f82 2590 return FALSE;
faf074a3 2591}
2592
38b73700 2593static gboolean enum_interrupt(void *hook_data, void *call_data)
2594{
7a4bdb54
YB
2595 LttvEvent *event;
2596 LttvTraceState *ts;
38b73700 2597
7a4bdb54
YB
2598 LttvNameTables *nt;
2599
2600
2601 GQuark action;
2602 guint irq;
2603 event = (LttvEvent *) call_data;
2604 if (strcmp(lttv_traceset_get_name_from_event(event),
2605 "lttng_statedump_interrupt") != 0)
2606 return FALSE;
2607 ts = event->state;
38b73700 2608
7a4bdb54
YB
2609 nt = ts->name_tables;
2610 irq = lttv_event_get_long_unsigned(event, "irq");
2611 action = g_quark_from_string(lttv_event_get_string(event,
2612 "action"));
90e19f82
AM
2613 expand_irq_table(ts, irq);
2614 nt->irq_names[irq] = action;
38b73700 2615
90e19f82 2616 return FALSE;
38b73700 2617}
2618
7a4bdb54 2619#ifdef BABEL_CLEANUP
27811799 2620static gboolean bdev_request_issue(void *hook_data, void *call_data)
2621{
7a4bdb54
YB
2622 LttvEvent *event;
2623 LttvTraceState *ts;
27811799 2624
7a4bdb54
YB
2625 guint major;
2626 guint minor;
2627 guint oper;
2628 guint32 devcode;
2629 gpointer bdev;
27811799 2630
7a4bdb54
YB
2631 event = (LttvEvent *) call_data;
2632 if (strcmp(lttv_traceset_get_name_from_event(event),
2633 "block_rq_issue") != 0)
2634 return FALSE;
27811799 2635
7a4bdb54
YB
2636 ts = event->state;
2637 major = lttv_event_get_long_unsigned(event,);
2638
2639 minor = lttv_event_get_long_unsigned(event,);
2640
2641 oper = lttv_event_get_long_unsigned(event,);
2642
2643 devcode = MKDEV(major,minor);
2644
2645 /* have we seen this block device before? */
2646 bdev = get_hashed_bdevstate(ts, devcode);
90e19f82
AM
2647 if(oper == 0)
2648 bdev_push_mode(bdev, LTTV_BDEV_BUSY_READING);
2649 else
2650 bdev_push_mode(bdev, LTTV_BDEV_BUSY_WRITING);
27811799 2651
90e19f82 2652 return FALSE;
27811799 2653}
2654
2655static gboolean bdev_request_complete(void *hook_data, void *call_data)
2656{
90e19f82
AM
2657 LttvTracefileState *s = (LttvTracefileState *)call_data;
2658 LttvTraceState *ts = (LttvTraceState *)s->parent.t_context;
2659 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
2660 LttvTraceHook *th = (LttvTraceHook *)hook_data;
27811799 2661
90e19f82
AM
2662 guint major = ltt_event_get_long_unsigned(e,
2663 lttv_trace_get_hook_field(th, 0));
2664 guint minor = ltt_event_get_long_unsigned(e,
2665 lttv_trace_get_hook_field(th, 1));
2666 //guint oper = ltt_event_get_long_unsigned(e,
2667 // lttv_trace_get_hook_field(th, 2));
59dc1f2a 2668 guint32 devcode = MKDEV(major,minor);
27811799 2669
90e19f82
AM
2670 /* have we seen this block device before? */
2671 gpointer bdev = get_hashed_bdevstate(ts, devcode);
27811799 2672
90e19f82
AM
2673 /* update block device */
2674 bdev_pop_mode(bdev);
27811799 2675
90e19f82 2676 return FALSE;
27811799 2677}
7a4bdb54
YB
2678#endif
2679#ifdef BABEL_CLEANUP
2680// We dont have the syscall table in LTTng 2.0
cf453ac7 2681static gboolean dump_syscall(void *hook_data, void *call_data)
2682{
90e19f82
AM
2683 LttvTracefileState *s = (LttvTracefileState *)call_data;
2684 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
2685 LttvNameTables *nt = ts->name_tables;
2686 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
2687 LttvTraceHook *th = (LttvTraceHook *)hook_data;
2688 guint id;
90e19f82 2689 char *symbol;
cf453ac7 2690
90e19f82 2691 id = ltt_event_get_unsigned(e, lttv_trace_get_hook_field(th, 0));
90e19f82 2692 symbol = ltt_event_get_string(e, lttv_trace_get_hook_field(th, 2));
cf453ac7 2693
90e19f82
AM
2694 expand_syscall_table(ts, id);
2695 nt->syscall_names[id] = g_quark_from_string(symbol);
cf453ac7 2696
90e19f82 2697 return FALSE;
cf453ac7 2698}
2699
2d0d580c 2700static gboolean dump_kprobe(void *hook_data, void *call_data)
2701{
90e19f82
AM
2702 LttvTracefileState *s = (LttvTracefileState *)call_data;
2703 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
2704 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
2705 LttvTraceHook *th = (LttvTraceHook *)hook_data;
2706 guint64 ip;
2707 char *symbol;
2d0d580c 2708
90e19f82
AM
2709 ip = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 0));
2710 symbol = ltt_event_get_string(e, lttv_trace_get_hook_field(th, 1));
2d0d580c 2711
90e19f82 2712 expand_kprobe_table(ts, ip, symbol);
2d0d580c 2713
90e19f82 2714 return FALSE;
2d0d580c 2715}
7a4bdb54
YB
2716#endif
2717#ifdef BABEL_CLEANUP
dc6b2467 2718static gboolean dump_softirq(void *hook_data, void *call_data)
2719{
7a4bdb54 2720
90e19f82
AM
2721 LttvTracefileState *s = (LttvTracefileState *)call_data;
2722 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
2723 LttvNameTables *nt = ts->name_tables;
2724 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
2725 LttvTraceHook *th = (LttvTraceHook *)hook_data;
2726 guint id;
90e19f82 2727 char *symbol;
dc6b2467 2728
90e19f82 2729 id = ltt_event_get_unsigned(e, lttv_trace_get_hook_field(th, 0));
90e19f82 2730 symbol = ltt_event_get_string(e, lttv_trace_get_hook_field(th, 2));
eb8871e7 2731
90e19f82
AM
2732 expand_soft_irq_table(ts, id);
2733 nt->soft_irq_names[id] = g_quark_from_string(symbol);
dc6b2467 2734
90e19f82 2735 return FALSE;
dc6b2467 2736
7a4bdb54
YB
2737}
2738#endif
0fb145c4
MD
2739static gboolean sched_try_wakeup(void *hook_data, void *call_data)
2740{
7a4bdb54
YB
2741 LttvEvent *event;
2742 LttvTraceState *ts;
90e19f82
AM
2743 LttvProcessState *process;
2744 gint woken_pid;
2745 guint woken_cpu;
7a4bdb54
YB
2746 LttTime timestamp;
2747
2748 event = (LttvEvent *) call_data;
2749 if (strcmp(lttv_traceset_get_name_from_event(event),
2750 "sched_wakeup") != 0)
2751 return FALSE;
068572ab 2752
7a4bdb54 2753 ts = event->state;
068572ab 2754
7a4bdb54 2755 woken_pid = lttv_event_get_long(event, "tid");
fc26eb1b 2756 woken_cpu = lttv_event_get_long(event, "target_cpu");
7a4bdb54
YB
2757
2758 timestamp = lttv_event_get_timestamp(event);
90e19f82 2759 process = lttv_state_find_process_or_create(
7a4bdb54
YB
2760 ts,
2761 woken_cpu, woken_pid,
2762 &timestamp);
6b1f0e27
FG
2763
2764 if (process->state->s == LTTV_STATE_WAIT || process->state->s == LTTV_STATE_WAIT_FORK)
2765 {
2766 process->state->s = LTTV_STATE_WAIT_CPU;
7a4bdb54 2767 process->state->change = timestamp;
6b1f0e27 2768 }
068572ab 2769
90e19f82 2770 g_debug("Wakeup: process %d on CPU %u\n", woken_pid, woken_cpu);
068572ab 2771
90e19f82 2772 return FALSE;
068572ab
CS
2773}
2774
b445142a 2775static gboolean schedchange(void *hook_data, void *call_data)
dc877563 2776{
7a4bdb54
YB
2777 LttvEvent *event;
2778 guint cpu;
2779 LttvTraceState *ts;
2780 LttvProcessState *process;
2781
2782
90e19f82
AM
2783 //LttvProcessState *old_process = ts->running_process[cpu];
2784
90e19f82
AM
2785 guint pid_in, pid_out;
2786 gint64 state_out;
d7f9f37b
YB
2787 //TODO ybrosseau 2012-07-13: manage this 20 in a constact or dynamically
2788 char next_comm[20];
7a4bdb54
YB
2789 LttTime timestamp;
2790 event = (LttvEvent *) call_data;
2791 if (strcmp(lttv_traceset_get_name_from_event(event),
2792 "sched_switch") != 0)
2793 return FALSE;
90e19f82 2794
7a4bdb54
YB
2795 cpu = lttv_traceset_get_cpuid_from_event(event);
2796 ts = event->state;
2797 process = ts->running_process[cpu];
58b4e4ae
YB
2798 pid_out = lttv_event_get_long(event, "prev_tid");
2799 pid_in = lttv_event_get_long(event, "next_tid");
7a4bdb54 2800 state_out = lttv_event_get_long(event, "prev_state");
90e19f82 2801
d7f9f37b
YB
2802 strncpy(next_comm, lttv_event_get_string(event, "next_comm"), 20);
2803 next_comm[20-1] = '\0';
2804
7a4bdb54
YB
2805 timestamp = lttv_event_get_timestamp(event);
2806
90e19f82
AM
2807 if(likely(process != NULL)) {
2808
2809 /* We could not know but it was not the idle process executing.
2810 This should only happen at the beginning, before the first schedule
2811 event, and when the initial information (current process for each CPU)
2812 is missing. It is not obvious how we could, after the fact, compensate
2813 the wrongly attributed statistics. */
2814
2815 //This test only makes sense once the state is known and if there is no
2816 //missing events. We need to silently ignore schedchange coming after a
2817 //process_free, or it causes glitches. (FIXME)
2818 //if(unlikely(process->pid != pid_out)) {
2819 // g_assert(process->pid == 0);
2820 //}
2821 if(process->pid == 0
2822 && process->state->t == LTTV_STATE_MODE_UNKNOWN) {
2823 if(pid_out == 0) {
f044974e
MD
2824 /*
2825 * Scheduling out of pid 0 at beginning of the trace.
2826 * We are typically in system call mode at this point although
2827 * (FIXME) we might be in a trap handler.
2828 */
90e19f82
AM
2829 g_assert(process->execution_stack->len == 1);
2830 process->state->t = LTTV_STATE_SYSCALL;
2831 process->state->s = LTTV_STATE_WAIT;
7a4bdb54
YB
2832 process->state->change = timestamp;
2833 process->state->entry = timestamp;
90e19f82
AM
2834 }
2835 } else {
2836 if(unlikely(process->state->s == LTTV_STATE_EXIT)) {
2837 process->state->s = LTTV_STATE_ZOMBIE;
7a4bdb54 2838 process->state->change = timestamp;
90e19f82
AM
2839 } else {
2840 if(unlikely(state_out == 0)) process->state->s = LTTV_STATE_WAIT_CPU;
2841 else process->state->s = LTTV_STATE_WAIT;
7a4bdb54 2842 process->state->change = timestamp;
90e19f82
AM
2843 }
2844
2845 if(state_out == 32 || state_out == 64) { /* EXIT_DEAD || TASK_DEAD */
2846 /* see sched.h for states */
7a4bdb54 2847 if (!exit_process(event, process)) {
90e19f82 2848 process->state->s = LTTV_STATE_DEAD;
7a4bdb54 2849 process->state->change = timestamp;
2fe13145 2850 }
90e19f82
AM
2851 }
2852 }
2853 }
2854 process = ts->running_process[cpu] = lttv_state_find_process_or_create(
7a4bdb54 2855 ts,
90e19f82 2856 cpu, pid_in,
7a4bdb54 2857 &timestamp);
90e19f82
AM
2858 process->state->s = LTTV_STATE_RUN;
2859 process->cpu = cpu;
348c6ba8 2860 // process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)s)->tf);
7a4bdb54 2861 process->state->change = timestamp;
d7f9f37b 2862 process->name = g_quark_from_string(next_comm);
90e19f82
AM
2863
2864 /* update cpu status */
2865 if(pid_in == 0)
2866 /* going to idle task */
7a4bdb54 2867 cpu_set_base_mode(&(ts->cpu_states[cpu]), LTTV_CPU_IDLE);
90e19f82
AM
2868 else {
2869 /* scheduling a real task.
2870 * we must be careful here:
2871 * if we just schedule()'ed to a process that is
2872 * in a trap, we must put the cpu in trap mode
2873 */
7a4bdb54 2874 cpu_set_base_mode(&(ts->cpu_states[cpu]), LTTV_CPU_BUSY);
90e19f82 2875 if(process->state->t == LTTV_STATE_TRAP)
7a4bdb54 2876 cpu_push_mode(&(ts->cpu_states[cpu]), LTTV_CPU_TRAP);
90e19f82
AM
2877 }
2878
2879 return FALSE;
dc877563 2880}
2881
eed2ef37 2882static gboolean process_fork(void *hook_data, void *call_data)
dc877563 2883{
7a4bdb54
YB
2884 LttvEvent *event;
2885 LttvTraceState *ts;
2886 LttvProcessState *process;
2887 LttvProcessState *child_process;
90e19f82
AM
2888 guint child_pid; /* In the Linux Kernel, there is one PID per thread. */
2889 guint child_tgid; /* tgid in the Linux kernel is the "real" POSIX PID. */
2890 //LttvProcessState *zombie_process;
7a4bdb54
YB
2891 guint cpu;
2892 LttTime timestamp;
90e19f82 2893
7a4bdb54
YB
2894 event = (LttvEvent *) call_data;
2895 if (strcmp(lttv_traceset_get_name_from_event(event),
2896 "sched_process_fork") != 0)
2897 return FALSE;
2898 cpu = lttv_traceset_get_cpuid_from_event(event);
2899 ts = event->state;
2900 process = ts->running_process[cpu];
2901 timestamp = lttv_event_get_timestamp(event);
2902
e865422c 2903 /* Skip Parent PID param */
90e19f82
AM
2904
2905 /* Child PID */
7a4bdb54
YB
2906 child_pid = lttv_event_get_long_unsigned(event, "child_tid");
2907 //ts->target_pid = child_pid;
90e19f82
AM
2908
2909 /* Child TGID */
7a4bdb54
YB
2910
2911 child_tgid = 0;
90e19f82
AM
2912
2913 /* Mathieu : it seems like the process might have been scheduled in before the
2914 * fork, and, in a rare case, might be the current process. This might happen
2915 * in a SMP case where we don't have enough precision on the clocks.
2916 *
2917 * Test reenabled after precision fixes on time. (Mathieu) */
791dffa6 2918#if 0
90e19f82
AM
2919 zombie_process = lttv_state_find_process(ts, ANY_CPU, child_pid);
2920
2921 if(unlikely(zombie_process != NULL)) {
2922 /* Reutilisation of PID. Only now we are sure that the old PID
2923 * has been released. FIXME : should know when release_task happens instead.
2924 */
2925 guint num_cpus = ltt_trace_get_num_cpu(ts->parent.t);
2926 guint i;
2927 for(i=0; i< num_cpus; i++) {
2928 g_assert(zombie_process != ts->running_process[i]);
2929 }
2930
2931 exit_process(s, zombie_process);
2932 }
791dffa6 2933#endif //0
90e19f82
AM
2934 g_assert(process->pid != child_pid);
2935 // FIXME : Add this test in the "known state" section
2936 // g_assert(process->pid == parent_pid);
2937 child_process = lttv_state_find_process(ts, ANY_CPU, child_pid);
2938 if(child_process == NULL) {
2939 child_process = lttv_state_create_process(ts, process, cpu,
2940 child_pid, child_tgid,
7a4bdb54 2941 LTTV_STATE_UNNAMED, &timestamp);
90e19f82
AM
2942 } else {
2943 /* The process has already been created : due to time imprecision between
2944 * multiple CPUs : it has been scheduled in before creation. Note that we
2945 * shouldn't have this kind of imprecision.
2946 *
2947 * Simply put a correct parent.
2948 */
2949 g_error("Process %u has been created at [%lu.%09lu] "
2950 "and inserted at [%lu.%09lu] before \n"
2951 "fork on cpu %u[%lu.%09lu].\n"
2952 "Probably an unsynchronized TSC problem on the traced machine.",
2953 child_pid,
2954 child_process->creation_time.tv_sec,
2955 child_process->creation_time.tv_nsec,
2956 child_process->insertion_time.tv_sec,
2957 child_process->insertion_time.tv_nsec,
7a4bdb54 2958 cpu, timestamp.tv_sec, timestamp.tv_nsec);
90e19f82
AM
2959 //g_assert(0); /* This is a problematic case : the process has been created
2960 // before the fork event */
2961 child_process->ppid = process->pid;
2962 child_process->tgid = child_tgid;
2963 }
2964 g_assert(child_process->name == LTTV_STATE_UNNAMED);
2965 child_process->name = process->name;
2966 child_process->brand = process->brand;
2967
2968 return FALSE;
dc877563 2969}
2970
7a4bdb54
YB
2971#ifdef BABEL_CLEANUP
2972//NO KTHREAD_CREATE in LTTng 2.0
89f8741a 2973/* We stamp a newly created process as kernel_thread.
2974 * The thread should not be running yet. */
7bfd7820 2975static gboolean process_kernel_thread(void *hook_data, void *call_data)
2976{
90e19f82
AM
2977 LttvTracefileState *s = (LttvTracefileState *)call_data;
2978 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
2979 LttvTraceHook *th = (LttvTraceHook *)hook_data;
2980 guint pid;
2981 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
2982 LttvProcessState *process;
2983 LttvExecutionState *es;
7bfd7820 2984
90e19f82
AM
2985 /* PID */
2986 pid = (guint)ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 0));
7a4bdb54 2987 //s->parent.target_pid = pid;
7bfd7820 2988
90e19f82
AM
2989 process = lttv_state_find_process_or_create(ts, ANY_CPU, pid,
2990 &ltt_time_zero);
2991 if (process->state->s != LTTV_STATE_DEAD) {
2992 process->execution_stack =
2993 g_array_set_size(process->execution_stack, 1);
2994 es = process->state =
2995 &g_array_index(process->execution_stack, LttvExecutionState, 0);
2996 es->t = LTTV_STATE_SYSCALL;
2997 }
2998 process->type = LTTV_STATE_KERNEL_THREAD;
7bfd7820 2999
90e19f82 3000 return FALSE;
7bfd7820 3001}
7a4bdb54 3002#endif
eed2ef37 3003static gboolean process_exit(void *hook_data, void *call_data)
dc877563 3004{
7a4bdb54
YB
3005 LttvEvent *event;
3006 LttvTraceState *ts;
90e19f82 3007 guint pid;
7a4bdb54 3008 guint cpu;
90e19f82 3009 LttvProcessState *process; // = ts->running_process[cpu];
eed2ef37 3010
7a4bdb54
YB
3011 event = (LttvEvent *) call_data;
3012 if (strcmp(lttv_traceset_get_name_from_event(event),
3013 "sched_process_exit") != 0)
3014 return FALSE;
3015 cpu = lttv_traceset_get_cpuid_from_event(event);
3016 ts = event->state;
3017 process = ts->running_process[cpu];
3018
fc26eb1b 3019 pid = lttv_event_get_long(event, "tid");
7a4bdb54 3020 //s->parent.target_pid = pid;
eed2ef37 3021
90e19f82
AM
3022 // FIXME : Add this test in the "known state" section
3023 // g_assert(process->pid == pid);
eed2ef37 3024
90e19f82
AM
3025 process = lttv_state_find_process(ts, ANY_CPU, pid);
3026 if(likely(process != NULL)) {
3027 process->state->s = LTTV_STATE_EXIT;
3028 }
3029 return FALSE;
2cdc690b 3030}
3031
eed2ef37 3032static gboolean process_free(void *hook_data, void *call_data)
2da61677 3033{
7a4bdb54
YB
3034 LttvEvent *event;
3035 LttvTraceState *ts;
3036 guint cpu;
90e19f82
AM
3037 guint release_pid;
3038 LttvProcessState *process;
3039
7a4bdb54
YB
3040 event = (LttvEvent *) call_data;
3041 if (strcmp(lttv_traceset_get_name_from_event(event),
3042 "sched_process_free") != 0)
3043 return FALSE;
3044 cpu = lttv_traceset_get_cpuid_from_event(event);
3045 ts = event->state;
3046 process = ts->running_process[cpu];
3047
90e19f82 3048 /* PID of the process to release */
fc26eb1b 3049 release_pid = lttv_event_get_long(event, "_tid");
7a4bdb54 3050 //s->parent.target_pid = release_pid;
90e19f82
AM
3051
3052 g_assert(release_pid != 0);
3053
3054 process = lttv_state_find_process(ts, ANY_CPU, release_pid);
3055 if(likely(process != NULL))
7a4bdb54 3056 exit_process(event, process);
90e19f82 3057 return FALSE;
2fe13145 3058//DISABLED
7a4bdb54 3059#if 0
90e19f82
AM
3060 if(likely(process != NULL)) {
3061 /* release_task is happening at kernel level : we can now safely release
3062 * the data structure of the process */
3063 //This test is fun, though, as it may happen that
3064 //at time t : CPU 0 : process_free
3065 //at time t+150ns : CPU 1 : schedule out
3066 //Clearly due to time imprecision, we disable it. (Mathieu)
3067 //If this weird case happen, we have no choice but to put the
3068 //Currently running process on the cpu to 0.
3069 //I re-enable it following time precision fixes. (Mathieu)
3070 //Well, in the case where an process is freed by a process on another CPU
3071 //and still scheduled, it happens that this is the schedchange that will
3072 //drop the last reference count. Do not free it here!
3073 guint num_cpus = ltt_trace_get_num_cpu(ts->parent.t);
3074 guint i;
3075 for(i=0; i< num_cpus; i++) {
3076 //g_assert(process != ts->running_process[i]);
3077 if(process == ts->running_process[i]) {
3078 //ts->running_process[i] = lttv_state_find_process(ts, i, 0);
3079 break;
3080 }
3081 }
3082 if(i == num_cpus) /* process is not scheduled */
3083 exit_process(s, process);
3084 }
3085
3086 return FALSE;
7a4bdb54 3087#endif //DISABLED
2da61677 3088}
3089
f4b88a7d 3090
3091static gboolean process_exec(void *hook_data, void *call_data)
7a4bdb54
YB
3092{
3093 LttvEvent *event;
3094 LttvTraceState *ts;
3095 guint cpu;
90e19f82 3096 //gchar *name;
7a4bdb54
YB
3097 LttvProcessState *process;
3098
3099 event = (LttvEvent *) call_data;
3100 if (strcmp(lttv_traceset_get_name_from_event(event),
3101 "sys_execve") != 0)
3102 return FALSE;
3103 cpu = lttv_traceset_get_cpuid_from_event(event);
3104 ts = event->state;
3105 process = ts->running_process[cpu];
f4b88a7d 3106
f63ebe51 3107#if 0//how to use a sequence that must be transformed in a string
90e19f82
AM
3108 /* PID of the process to release */
3109 guint64 name_len = ltt_event_field_element_number(e,
3110 lttv_trace_get_hook_field(th, 0));
3111 //name = ltt_event_get_string(e, lttv_trace_get_hook_field(th, 0));
3112 LttField *child = ltt_event_field_element_select(e,
3113 lttv_trace_get_hook_field(th, 0), 0);
3114 gchar *name_begin =
3115 (gchar*)(ltt_event_data(e)+ltt_event_field_offset(e, child));
3116 gchar *null_term_name = g_new(gchar, name_len+1);
3117 memcpy(null_term_name, name_begin, name_len);
3118 null_term_name[name_len] = '\0';
3119 process->name = g_quark_from_string(null_term_name);
f63ebe51 3120#endif //0
3121
7a4bdb54
YB
3122 process->name = g_quark_from_string(lttv_event_get_string(event,
3123 "filename"));
90e19f82
AM
3124 process->brand = LTTV_STATE_UNBRANDED;
3125 //g_free(null_term_name);
3126 return FALSE;
f4b88a7d 3127}
7a4bdb54 3128#ifdef BABEL_CLEANUP
7b5f6cf1 3129static gboolean thread_brand(void *hook_data, void *call_data)
3130{
90e19f82
AM
3131 LttvTracefileState *s = (LttvTracefileState *)call_data;
3132 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
3133 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
3134 LttvTraceHook *th = (LttvTraceHook *)hook_data;
3135 gchar *name;
3136 guint cpu = s->cpu;
3137 LttvProcessState *process = ts->running_process[cpu];
7b5f6cf1 3138
90e19f82
AM
3139 name = ltt_event_get_string(e, lttv_trace_get_hook_field(th, 0));
3140 process->brand = g_quark_from_string(name);
7b5f6cf1 3141
90e19f82 3142 return FALSE;
7b5f6cf1 3143}
7a4bdb54
YB
3144#endif
3145#if 0
3146 // TODO We only have sys_open, without the FD
3147 // manage to do somehting better
8c108c1c
PMF
3148static gboolean fs_open(void *hook_data, void *call_data)
3149{
90e19f82
AM
3150 LttvTracefileState *s = (LttvTracefileState *)call_data;
3151 LttvTraceState *ts = (LttvTraceState *)s->parent.t_context;
3152 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
3153 LttvTraceHook *th = (LttvTraceHook *)hook_data;
3154 struct marker_field *f;
3155 guint cpu = s->cpu;
3156 int fd;
3157 char *filename;
3158 LttvProcessState *process = ts->running_process[cpu];
8c108c1c 3159
90e19f82
AM
3160 f = lttv_trace_get_hook_field(th, 0);
3161 fd = ltt_event_get_int(e, f);
8c108c1c 3162
90e19f82
AM
3163 f = lttv_trace_get_hook_field(th, 1);
3164 filename = ltt_event_get_string(e, f);
8c108c1c 3165
90e19f82
AM
3166 g_hash_table_insert(process->fds, (gpointer)(long)fd,
3167 (gpointer)(unsigned long)g_quark_from_string(filename));
8c108c1c 3168
90e19f82 3169 return FALSE;
8c108c1c 3170}
7a4bdb54 3171#endif
9ba16662
MD
3172static void print_stack(LttvProcessState *process)
3173{
3174 LttvExecutionState *es;
3175 int i;
3176
3177 g_debug("Execution stack for process %u %s:\n",
90e19f82 3178 process->pid, g_quark_to_string(process->name));
9ba16662
MD
3179
3180 for (i = 0; i < process->execution_stack->len; i++) {
3181 es = &g_array_index(process->execution_stack,
90e19f82 3182 LttvExecutionState, i);
9ba16662 3183 g_debug("Depth %d mode %s submode %s status %s\n",
90e19f82
AM
3184 i, g_quark_to_string(es->t),
3185 g_quark_to_string(es->n),
3186 g_quark_to_string(es->s));
9ba16662
MD
3187 }
3188
3189}
3190
90e19f82
AM
3191static void fix_process(gpointer key, gpointer value, gpointer user_data)
3192{
3193 LttvProcessState *process;
3194 LttvExecutionState *es;
3195 process = (LttvProcessState *)value;
3196 LttTime *timestamp = (LttTime*)user_data;
3197
3198 print_stack(process);
3199
3200 if(process->type == LTTV_STATE_KERNEL_THREAD) {
3201 es = &g_array_index(process->execution_stack, LttvExecutionState, 0);
f044974e 3202 if(es->t == LTTV_STATE_MAYBE_SYSCALL) {
90e19f82
AM
3203 es->t = LTTV_STATE_SYSCALL;
3204 es->n = LTTV_STATE_SUBMODE_NONE;
3205 es->entry = *timestamp;
3206 es->change = *timestamp;
3207 es->cum_cpu_time = ltt_time_zero;
3208 if(es->s == LTTV_STATE_UNNAMED)
3209 es->s = LTTV_STATE_WAIT;
3210 }
9ba16662 3211 } else {
90e19f82 3212 es = &g_array_index(process->execution_stack, LttvExecutionState, 0);
f044974e 3213 if(es->t == LTTV_STATE_MAYBE_USER_MODE) {
90e19f82
AM
3214 es->t = LTTV_STATE_USER_MODE;
3215 es->n = LTTV_STATE_SUBMODE_NONE;
3216 es->entry = *timestamp;
3217 //g_assert(timestamp->tv_sec != 0);
3218 es->change = *timestamp;
3219 es->cum_cpu_time = ltt_time_zero;
3220 if(es->s == LTTV_STATE_UNNAMED)
3221 es->s = LTTV_STATE_RUN;
3222
3223 if(process->execution_stack->len == 1) {
3224 /* Still in bottom unknown mode, means we either:
3225 * - never did a system call
3226 * - are scheduled out from user mode.
3227 * May be either in user mode, syscall mode, running or waiting.*/
3228 /* CHECK : we may be tagging syscall mode when being user mode
3229 * (should be fixed now) */
3230 if (es->s == LTTV_STATE_WAIT_CPU) {
3231 /* nothing to do: scheduled out from userspace */
3232 } else {
3233 process->execution_stack =
3234 g_array_set_size(process->execution_stack, 2);
3235 es = process->state = &g_array_index(process->execution_stack,
3236 LttvExecutionState, 1);
3237 es->t = LTTV_STATE_SYSCALL;
3238 es->n = LTTV_STATE_SUBMODE_NONE;
3239 es->entry = *timestamp;
3240 //g_assert(timestamp->tv_sec != 0);
3241 es->change = *timestamp;
3242 es->cum_cpu_time = ltt_time_zero;
3243 if(es->s == LTTV_STATE_WAIT_FORK)
3244 es->s = LTTV_STATE_WAIT;
3245 }
3246 }
3247 }
9ba16662 3248 }
c3b3b60b 3249}
3250
3251static gboolean statedump_end(void *hook_data, void *call_data)
3252{
7a4bdb54
YB
3253 LttvEvent *event;
3254 LttvTraceState *ts;
3255 LttTime timestamp;
90e19f82
AM
3256 //LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
3257 //LttvTraceHook *th = (LttvTraceHook *)hook_data;
7a4bdb54
YB
3258 event = (LttvEvent *) call_data;
3259 if (strcmp(lttv_traceset_get_name_from_event(event),
3260 "lttng_statedump_end") != 0)
3261 return FALSE;
3262
3263 ts = event->state;
3264 timestamp = lttv_event_get_timestamp(event);
c3b3b60b 3265
90e19f82
AM
3266 /* For all processes */
3267 /* if kernel thread, if stack[0] is unknown, set to syscall mode, wait */
3268 /* else, if stack[0] is unknown, set to user mode, running */
0ceef9de 3269
7a4bdb54 3270 g_hash_table_foreach(ts->processes, fix_process, &timestamp);
90e19f82
AM
3271
3272 return FALSE;
c3b3b60b 3273}
3274
b3fd4c02 3275static gboolean enum_process_state(void *hook_data, void *call_data)
3276{
7a4bdb54
YB
3277 LttvEvent *event;
3278 LttvTraceState *ts;
3279 LttTime timestamp;
90e19f82
AM
3280 guint parent_pid;
3281 guint pid;
3282 guint tgid;
3283 gchar * command;
7a4bdb54 3284 guint cpu;
90e19f82 3285 LttvProcessState *parent_process;
7a4bdb54
YB
3286 LttvProcessState *process;
3287
3288 guint type;
90e19f82
AM
3289 LttvExecutionState *es;
3290 guint i, nb_cpus;
3291
7a4bdb54
YB
3292 event = (LttvEvent *) call_data;
3293 if (strcmp(lttv_traceset_get_name_from_event(event),
3294 "lttng_statedump_process_state") != 0)
3295 return FALSE;
3296 cpu = lttv_traceset_get_cpuid_from_event(event);
3297 ts = event->state;
3298 process = ts->running_process[cpu];
3299 timestamp = lttv_event_get_timestamp(event);
3300
90e19f82 3301 /* PID */
fc26eb1b 3302 pid = lttv_event_get_long(event, "tid");
7a4bdb54 3303 //s->parent.target_pid = pid;
90e19f82
AM
3304
3305 /* Parent PID */
fc26eb1b 3306 parent_pid = lttv_event_get_long(event, "ppid");
90e19f82
AM
3307
3308 /* Command name */
7a4bdb54 3309 command = lttv_event_get_string(event, "name");
90e19f82
AM
3310
3311 /* type */
7a4bdb54 3312
fc26eb1b 3313 type = lttv_event_get_long(event, "type");
90e19f82
AM
3314
3315 //FIXME: type is rarely used, enum must match possible types.
3316
e865422c 3317 /* Skip mode 4th param */
90e19f82 3318
e865422c 3319 /* Skip submode 5th param */
90e19f82 3320
e865422c 3321 /* Skip status 6th param */
90e19f82 3322 /* TGID */
fc26eb1b 3323 tgid = lttv_event_get_long(event, "pid");
7a4bdb54 3324
90e19f82 3325 if(pid == 0) {
7a4bdb54 3326 nb_cpus = lttv_trace_get_num_cpu(ts->trace);
90e19f82
AM
3327 for(i=0; i<nb_cpus; i++) {
3328 process = lttv_state_find_process(ts, i, pid);
3329 g_assert(process != NULL);
3330
3331 process->ppid = parent_pid;
3332 process->tgid = tgid;
3333 process->name = g_quark_from_string(command);
3334 es = &g_array_index(process->execution_stack, LttvExecutionState, 0);
3335 process->type = LTTV_STATE_KERNEL_THREAD;
3336 }
3337
3338 } else {
3339 /* The process might exist if a process was forked while performing the
3340 * state dump. */
3341 process = lttv_state_find_process(ts, ANY_CPU, pid);
3342 if(process == NULL) {
3343 parent_process = lttv_state_find_process(ts, ANY_CPU, parent_pid);
3344 process = lttv_state_create_process(ts, parent_process, cpu,
3345 pid, tgid, g_quark_from_string(command),
7a4bdb54 3346 &timestamp);
90e19f82
AM
3347
3348 /* Keep the stack bottom : a running user mode */
3349 /* Disabled because of inconsistencies in the current statedump states. */
7a4bdb54
YB
3350 //if(type == LTTV_STATE_KERNEL_THREAD) {
3351 if(type == 1) {
90e19f82
AM
3352 /* Only keep the bottom
3353 * FIXME Kernel thread : can be in syscall or interrupt or trap. */
3354 /* Will cause expected trap when in fact being syscall (even after end of
3355 * statedump event)
3356 * Will cause expected interrupt when being syscall. (only before end of
3357 * statedump event) */
3358 // This will cause a "popping last state on stack, ignoring it."
3359 process->execution_stack = g_array_set_size(process->execution_stack, 1);
3360 es = process->state = &g_array_index(process->execution_stack,
3361 LttvExecutionState, 0);
3362 process->type = LTTV_STATE_KERNEL_THREAD;
f044974e 3363 es->t = LTTV_STATE_MAYBE_SYSCALL;
90e19f82
AM
3364 es->s = LTTV_STATE_UNNAMED;
3365 es->n = LTTV_STATE_SUBMODE_UNKNOWN;
f044974e
MD
3366 //es->s = status;
3367 //es->n = submode;
90e19f82
AM
3368 } else {
3369 /* User space process :
3370 * bottom : user mode
3371 * either currently running or scheduled out.
3372 * can be scheduled out because interrupted in (user mode or in syscall)
3373 * or because of an explicit call to the scheduler in syscall. Note that
3374 * the scheduler call comes after the irq_exit, so never in interrupt
3375 * context. */
3376 // temp workaround : set size to 1 : only have user mode bottom of stack.
3377 // will cause g_info message of expected syscall mode when in fact being
3378 // in user mode. Can also cause expected trap when in fact being user
3379 // mode in the event of a page fault reenabling interrupts in the handler.
3380 // Expected syscall and trap can also happen after the end of statedump
3381 // This will cause a "popping last state on stack, ignoring it."
3382 process->execution_stack = g_array_set_size(process->execution_stack, 1);
3383 es = process->state = &g_array_index(process->execution_stack,
3384 LttvExecutionState, 0);
f044974e 3385 es->t = LTTV_STATE_MAYBE_USER_MODE;
90e19f82
AM
3386 es->s = LTTV_STATE_UNNAMED;
3387 es->n = LTTV_STATE_SUBMODE_UNKNOWN;
f044974e
MD
3388 //es->s = status;
3389 //es->n = submode;
90e19f82
AM
3390 }
3391 #if 0
3392 /* UNKNOWN STATE */
3393 {
3394 es = process->state = &g_array_index(process->execution_stack,
3395 LttvExecutionState, 1);
3396 es->t = LTTV_STATE_MODE_UNKNOWN;
3397 es->s = LTTV_STATE_UNNAMED;
3398 es->n = LTTV_STATE_SUBMODE_UNKNOWN;
3399 }
3400 #endif //0
3401 } else {
3402 /* The process has already been created :
3403 * Probably was forked while dumping the process state or
3404 * was simply scheduled in prior to get the state dump event.
3405 */
3406 process->ppid = parent_pid;
3407 process->tgid = tgid;
3408 process->name = g_quark_from_string(command);
3409 process->type = type;
3410 es = &g_array_index(process->execution_stack, LttvExecutionState, 0);
c3b3b60b 3411#if 0
90e19f82
AM
3412 if(es->t == LTTV_STATE_MODE_UNKNOWN) {
3413 if(type == LTTV_STATE_KERNEL_THREAD)
3414 es->t = LTTV_STATE_SYSCALL;
3415 else
3416 es->t = LTTV_STATE_USER_MODE;
3417 }
cab321cf 3418#endif //0
90e19f82
AM
3419 /* Don't mess around with the stack, it will eventually become
3420 * ok after the end of state dump. */
3421 }
3422 }
3423
3424 return FALSE;
b3fd4c02 3425}
f4b88a7d 3426
7a4bdb54
YB
3427
3428
58c88a41 3429gint lttv_state_hook_add_event_hooks(void *hook_data, void *call_data)
3430{
7a4bdb54 3431 LttvTraceset *traceset = (LttvTraceset *)(call_data);
58c88a41 3432
7a4bdb54 3433 lttv_state_add_event_hooks(traceset);
58c88a41 3434
90e19f82 3435 return 0;
58c88a41 3436}
dc877563 3437
7a4bdb54 3438void lttv_state_add_event_hooks(LttvTraceset *traceset)
dc877563 3439{
7a4bdb54
YB
3440 gboolean result;
3441
3442 LttvAttributeValue value;
3443 LttvHooks*event_hook;
a7598d50 3444#ifdef BABEL_CLEANUP
7a4bdb54
YB
3445 LttvIAttribute *attributes = LTTV_IATTRIBUTE(lttv_global_attributes());
3446 result = lttv_iattribute_find_by_path(attributes, "hooks/event",
3447 LTTV_POINTER, &value);
3448 g_assert(result);
3449 event_hook = *(value.v_pointer);
a7598d50
YB
3450#endif
3451 //TODO ybrosseau 2012-07-12: Validate that using traceset hooks instead of the global one is valid
3452 //Use traceset hooks
3453 event_hook = lttv_traceset_get_hooks(traceset);
7a4bdb54
YB
3454 g_assert(event_hook);
3455
3456 lttv_hooks_add(event_hook,syscall_entry , NULL, LTTV_PRIO_STATE);
3457 lttv_hooks_add(event_hook,syscall_exit , NULL, LTTV_PRIO_STATE);
3458 lttv_hooks_add(event_hook,irq_entry , NULL, LTTV_PRIO_STATE);
3459 lttv_hooks_add(event_hook,irq_exit , NULL, LTTV_PRIO_STATE);
3460 lttv_hooks_add(event_hook,soft_irq_raise , NULL, LTTV_PRIO_STATE);
3461 lttv_hooks_add(event_hook,soft_irq_entry , NULL, LTTV_PRIO_STATE);
3462 lttv_hooks_add(event_hook,soft_irq_exit , NULL, LTTV_PRIO_STATE);
3463 lttv_hooks_add(event_hook,schedchange , NULL, LTTV_PRIO_STATE);
3464 lttv_hooks_add(event_hook,sched_try_wakeup , NULL, LTTV_PRIO_STATE);
3465 lttv_hooks_add(event_hook,process_exit , NULL, LTTV_PRIO_STATE);
3466 lttv_hooks_add(event_hook,process_free , NULL, LTTV_PRIO_STATE);
3467 lttv_hooks_add(event_hook,process_exec , NULL, LTTV_PRIO_STATE);
3468 lttv_hooks_add(event_hook,enum_process_state , NULL, LTTV_PRIO_STATE);
3469 lttv_hooks_add(event_hook,statedump_end , NULL, LTTV_PRIO_STATE);
3470 lttv_hooks_add(event_hook,enum_interrupt , NULL, LTTV_PRIO_STATE);
3471
3472#ifdef BABEL_CLEANUP //For the whole function this time
3473 guint i, j, k, nb_trace;
90e19f82 3474 LttvTraceState *ts;
90e19f82 3475 GArray *hooks;
7a4bdb54 3476 // LttvTraceHook *th;
90e19f82
AM
3477 LttvAttributeValue val;
3478
3479 nb_trace = lttv_traceset_number(traceset);
7a4bdb54
YB
3480 for (i = 0 ; i < nb_trace ; i++) {
3481 ts = lttv_traceset_get(traceset, i)-;
90e19f82
AM
3482
3483 /* Find the eventtype id for the following events and register the
3484 associated by id hooks. */
3485
3486 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 20);
3487 //hooks = g_array_set_size(hooks, 19); // Max possible number of hooks.
3488 //hn = 0;
3489
7a4bdb54 3490 lttv_trace_find_hook(tss->parent.t,
90e19f82
AM
3491 LTT_CHANNEL_KERNEL,
3492 LTT_EVENT_SYSCALL_ENTRY,
3493 FIELD_ARRAY(LTT_FIELD_SYSCALL_ID),
3494 syscall_entry, NULL, &hooks);
3495
3496 lttv_trace_find_hook(ts->parent.t,
3497 LTT_CHANNEL_KERNEL,
3498 LTT_EVENT_SYSCALL_EXIT,
3499 NULL,
3500 syscall_exit, NULL, &hooks);
3501
7a4bdb54 3502#ifdef BABEL_CLEANUP
90e19f82
AM
3503 lttv_trace_find_hook(ts->parent.t,
3504 LTT_CHANNEL_KERNEL,
3505 LTT_EVENT_TRAP_ENTRY,
3506 FIELD_ARRAY(LTT_FIELD_TRAP_ID),
3507 trap_entry, NULL, &hooks);
3508
3509 lttv_trace_find_hook(ts->parent.t,
3510 LTT_CHANNEL_KERNEL,
3511 LTT_EVENT_TRAP_EXIT,
3512 NULL,
3513 trap_exit, NULL, &hooks);
7a4bdb54 3514#endif /* BABEL_CLEANUP */
90e19f82
AM
3515
3516 lttv_trace_find_hook(ts->parent.t,
3517 LTT_CHANNEL_KERNEL,
3518 LTT_EVENT_PAGE_FAULT_ENTRY,
3519 FIELD_ARRAY(LTT_FIELD_TRAP_ID),
3520 trap_entry, NULL, &hooks);
3521
3522 lttv_trace_find_hook(ts->parent.t,
3523 LTT_CHANNEL_KERNEL,
3524 LTT_EVENT_PAGE_FAULT_EXIT,
3525 NULL,
3526 trap_exit, NULL, &hooks);
3527
7a4bdb54 3528#ifdef BABEL_CLEANUP
90e19f82
AM
3529 lttv_trace_find_hook(ts->parent.t,
3530 LTT_CHANNEL_KERNEL,
3531 LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY,
3532 FIELD_ARRAY(LTT_FIELD_TRAP_ID),
3533 trap_entry, NULL, &hooks);
3534
3535 lttv_trace_find_hook(ts->parent.t,
3536 LTT_CHANNEL_KERNEL,
3537 LTT_EVENT_PAGE_FAULT_NOSEM_EXIT,
3538 NULL,
3539 trap_exit, NULL, &hooks);
7a4bdb54 3540#endif /* BABEL_CLEANUP */
90e19f82
AM
3541
3542 lttv_trace_find_hook(ts->parent.t,
3543 LTT_CHANNEL_KERNEL,
3544 LTT_EVENT_IRQ_ENTRY,
3545 FIELD_ARRAY(LTT_FIELD_IRQ_ID),
3546 irq_entry, NULL, &hooks);
3547
3548 lttv_trace_find_hook(ts->parent.t,
3549 LTT_CHANNEL_KERNEL,
3550 LTT_EVENT_IRQ_EXIT,
3551 NULL,
3552 irq_exit, NULL, &hooks);
3553
3554 lttv_trace_find_hook(ts->parent.t,
3555 LTT_CHANNEL_KERNEL,
3556 LTT_EVENT_SOFT_IRQ_RAISE,
3557 FIELD_ARRAY(LTT_FIELD_SOFT_IRQ_ID),
3558 soft_irq_raise, NULL, &hooks);
3559
3560 lttv_trace_find_hook(ts->parent.t,
3561 LTT_CHANNEL_KERNEL,
3562 LTT_EVENT_SOFT_IRQ_ENTRY,
3563 FIELD_ARRAY(LTT_FIELD_SOFT_IRQ_ID),
3564 soft_irq_entry, NULL, &hooks);
3565
3566 lttv_trace_find_hook(ts->parent.t,
3567 LTT_CHANNEL_KERNEL,
3568 LTT_EVENT_SOFT_IRQ_EXIT,
3569 NULL,
3570 soft_irq_exit, NULL, &hooks);
3571
3572 lttv_trace_find_hook(ts->parent.t,
3573 LTT_CHANNEL_KERNEL,
3574 LTT_EVENT_SCHED_SCHEDULE,
3575 FIELD_ARRAY(LTT_FIELD_PREV_PID, LTT_FIELD_NEXT_PID,
3576 LTT_FIELD_PREV_STATE),
3577 schedchange, NULL, &hooks);
3578
3579 lttv_trace_find_hook(ts->parent.t,
3580 LTT_CHANNEL_KERNEL,
3581 LTT_EVENT_SCHED_TRY_WAKEUP,
3582 FIELD_ARRAY(LTT_FIELD_PID, LTT_FIELD_CPU_ID, LTT_FIELD_STATE),
3583 sched_try_wakeup, NULL, &hooks);
3584
3585 lttv_trace_find_hook(ts->parent.t,
3586 LTT_CHANNEL_KERNEL,
3587 LTT_EVENT_PROCESS_FORK,
3588 FIELD_ARRAY(LTT_FIELD_PARENT_PID, LTT_FIELD_CHILD_PID,
3589 LTT_FIELD_CHILD_TGID),
3590 process_fork, NULL, &hooks);
3591
3592 lttv_trace_find_hook(ts->parent.t,
3593 LTT_CHANNEL_KERNEL,
3594 LTT_EVENT_KTHREAD_CREATE,
3595 FIELD_ARRAY(LTT_FIELD_PID),
3596 process_kernel_thread, NULL, &hooks);
3597
3598 lttv_trace_find_hook(ts->parent.t,
3599 LTT_CHANNEL_KERNEL,
3600 LTT_EVENT_PROCESS_EXIT,
3601 FIELD_ARRAY(LTT_FIELD_PID),
3602 process_exit, NULL, &hooks);
3603
3604 lttv_trace_find_hook(ts->parent.t,
3605 LTT_CHANNEL_KERNEL,
3606 LTT_EVENT_PROCESS_FREE,
3607 FIELD_ARRAY(LTT_FIELD_PID),
3608 process_free, NULL, &hooks);
3609
3610 lttv_trace_find_hook(ts->parent.t,
3611 LTT_CHANNEL_FS,
3612 LTT_EVENT_EXEC,
3613 FIELD_ARRAY(LTT_FIELD_FILENAME),
3614 process_exec, NULL, &hooks);
3615
3616 lttv_trace_find_hook(ts->parent.t,
3617 LTT_CHANNEL_USERSPACE,
3618 LTT_EVENT_THREAD_BRAND,
3619 FIELD_ARRAY(LTT_FIELD_NAME),
3620 thread_brand, NULL, &hooks);
3621
3622 /* statedump-related hooks */
3623 lttv_trace_find_hook(ts->parent.t,
3624 LTT_CHANNEL_TASK_STATE,
3625 LTT_EVENT_PROCESS_STATE,
3626 FIELD_ARRAY(LTT_FIELD_PID, LTT_FIELD_PARENT_PID, LTT_FIELD_NAME,
3627 LTT_FIELD_TYPE, LTT_FIELD_MODE, LTT_FIELD_SUBMODE,
3628 LTT_FIELD_STATUS, LTT_FIELD_TGID),
3629 enum_process_state, NULL, &hooks);
3630
3631 lttv_trace_find_hook(ts->parent.t,
3632 LTT_CHANNEL_GLOBAL_STATE,
3633 LTT_EVENT_STATEDUMP_END,
3634 NULL,
3635 statedump_end, NULL, &hooks);
3636
3637 lttv_trace_find_hook(ts->parent.t,
3638 LTT_CHANNEL_IRQ_STATE,
3639 LTT_EVENT_LIST_INTERRUPT,
3640 FIELD_ARRAY(LTT_FIELD_ACTION, LTT_FIELD_IRQ_ID),
3641 enum_interrupt, NULL, &hooks);
3642
3643 lttv_trace_find_hook(ts->parent.t,
3644 LTT_CHANNEL_BLOCK,
3645 LTT_EVENT_REQUEST_ISSUE,
3646 FIELD_ARRAY(LTT_FIELD_MAJOR, LTT_FIELD_MINOR, LTT_FIELD_OPERATION),
3647 bdev_request_issue, NULL, &hooks);
3648
3649 lttv_trace_find_hook(ts->parent.t,
3650 LTT_CHANNEL_BLOCK,
3651 LTT_EVENT_REQUEST_COMPLETE,
3652 FIELD_ARRAY(LTT_FIELD_MAJOR, LTT_FIELD_MINOR, LTT_FIELD_OPERATION),
3653 bdev_request_complete, NULL, &hooks);
3654
3655 lttv_trace_find_hook(ts->parent.t,
3656 LTT_CHANNEL_USERSPACE,
3657 LTT_EVENT_FUNCTION_ENTRY,
3658 FIELD_ARRAY(LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE),
3659 function_entry, NULL, &hooks);
3660
3661 lttv_trace_find_hook(ts->parent.t,
3662 LTT_CHANNEL_USERSPACE,
3663 LTT_EVENT_FUNCTION_EXIT,
3664 FIELD_ARRAY(LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE),
3665 function_exit, NULL, &hooks);
3666
3667 lttv_trace_find_hook(ts->parent.t,
3668 LTT_CHANNEL_SYSCALL_STATE,
3669 LTT_EVENT_SYS_CALL_TABLE,
3670 FIELD_ARRAY(LTT_FIELD_ID, LTT_FIELD_ADDRESS, LTT_FIELD_SYMBOL),
3671 dump_syscall, NULL, &hooks);
3672
3673 lttv_trace_find_hook(ts->parent.t,
3674 LTT_CHANNEL_KPROBE_STATE,
3675 LTT_EVENT_KPROBE_TABLE,
3676 FIELD_ARRAY(LTT_FIELD_IP, LTT_FIELD_SYMBOL),
3677 dump_kprobe, NULL, &hooks);
3678
3679 lttv_trace_find_hook(ts->parent.t,
3680 LTT_CHANNEL_SOFTIRQ_STATE,
3681 LTT_EVENT_SOFTIRQ_VEC,
3682 FIELD_ARRAY(LTT_FIELD_ID, LTT_FIELD_ADDRESS, LTT_FIELD_SYMBOL),
3683 dump_softirq, NULL, &hooks);
3684
3685 lttv_trace_find_hook(ts->parent.t,
3686 LTT_CHANNEL_FS,
3687 LTT_EVENT_OPEN,
3688 FIELD_ARRAY(LTT_FIELD_FD, LTT_FIELD_FILENAME),
3689 fs_open, NULL, &hooks);
3690
3691 /* Add these hooks to each event_by_id hooks list */
3692
3693 nb_tracefile = ts->parent.tracefiles->len;
3694
3695 for(j = 0 ; j < nb_tracefile ; j++) {
3696 tfs =
3697 LTTV_TRACEFILE_STATE(g_array_index(ts->parent.tracefiles,
3698 LttvTracefileContext*, j));
3699
3700 for(k = 0 ; k < hooks->len ; k++) {
3701 th = &g_array_index(hooks, LttvTraceHook, k);
3702 if (th->mdata == tfs->parent.tf->mdata)
3703 lttv_hooks_add(
3704 lttv_hooks_by_id_find(tfs->parent.event_by_id, th->id),
3705 th->h,
3706 th,
3707 LTTV_PRIO_STATE);
3708 }
3709 }
3710 lttv_attribute_find(ts->parent.a, LTTV_STATE_HOOKS, LTTV_POINTER, &val);
3711 *(val.v_pointer) = hooks;
3712 }
7a4bdb54 3713#endif
dc877563 3714}
3715
58c88a41 3716gint lttv_state_hook_remove_event_hooks(void *hook_data, void *call_data)
3717{
58c88a41 3718
58b4e4ae
YB
3719 LttvTraceset *traceset = (LttvTraceset*)(call_data);
3720
3721 lttv_state_remove_event_hooks(traceset);
3722
90e19f82 3723 return 0;
58c88a41 3724}
58b4e4ae
YB
3725
3726void lttv_state_remove_event_hooks(LttvTraceset *traceset)
dc877563 3727{
dc877563 3728
90e19f82 3729 guint i, j, k, nb_trace, nb_tracefile;
dc877563 3730
58b4e4ae 3731 //LttvTraceState *ts;
dc877563 3732
58b4e4ae 3733 //GArray *hooks;
dc877563 3734
58b4e4ae 3735 //LttvTraceHook *th;
dc877563 3736
58b4e4ae 3737 //LttvAttributeValue val;
dc877563 3738
58b4e4ae
YB
3739 LttvHooks*event_hook;
3740 //TODO ybrosseau 2012-07-17 validate this. Reversed what's done in the add
3741 event_hook = lttv_traceset_get_hooks(traceset);
dc877563 3742
58b4e4ae
YB
3743 g_assert(event_hook);
3744
3745
3746 lttv_hooks_remove(event_hook,syscall_entry );
3747 lttv_hooks_remove(event_hook,syscall_exit);
3748 lttv_hooks_remove(event_hook,irq_entry );
3749 lttv_hooks_remove(event_hook,irq_exit );
3750 lttv_hooks_remove(event_hook,soft_irq_raise);
3751 lttv_hooks_remove(event_hook,soft_irq_entry);
3752 lttv_hooks_remove(event_hook,soft_irq_exit);
3753 lttv_hooks_remove(event_hook,schedchange);
3754 lttv_hooks_remove(event_hook,sched_try_wakeup);
3755 lttv_hooks_remove(event_hook,process_exit);
3756 lttv_hooks_remove(event_hook,process_free);
3757 lttv_hooks_remove(event_hook,process_exec);
3758 lttv_hooks_remove(event_hook,enum_process_state);
3759 lttv_hooks_remove(event_hook,statedump_end);
3760 lttv_hooks_remove(event_hook,enum_interrupt);
3761#ifdef BABEL_CLEANUP
90e19f82
AM
3762 nb_trace = lttv_traceset_number(traceset);
3763 for(i = 0 ; i < nb_trace ; i++) {
58b4e4ae 3764 ts = lttv_traceset_get(i);
7df20ca4 3765
90e19f82
AM
3766 lttv_attribute_find(ts->parent.a, LTTV_STATE_HOOKS, LTTV_POINTER, &val);
3767 hooks = *(val.v_pointer);
dc877563 3768
90e19f82 3769 /* Remove these hooks from each event_by_id hooks list */
dc877563 3770
90e19f82 3771 nb_tracefile = ts->parent.tracefiles->len;
dbb7bb09 3772
90e19f82
AM
3773 for(j = 0 ; j < nb_tracefile ; j++) {
3774 tfs =
3775 LTTV_TRACEFILE_STATE(g_array_index(ts->parent.tracefiles,
3776 LttvTracefileContext*, j));
dc877563 3777
90e19f82
AM
3778 for(k = 0 ; k < hooks->len ; k++) {
3779 th = &g_array_index(hooks, LttvTraceHook, k);
3780 if (th->mdata == tfs->parent.tf->mdata)
3781 lttv_hooks_remove_data(
3782 lttv_hooks_by_id_find(tfs->parent.event_by_id, th->id),
3783 th->h,
3784 th);
3785 }
3786 }
3787 lttv_trace_hook_remove_all(&hooks);
3788 g_array_free(hooks, TRUE);
3789 }
7a4bdb54 3790#endif
58b4e4ae
YB
3791}
3792
3793
eed2ef37 3794static gboolean state_save_event_hook(void *hook_data, void *call_data)
3795{
90e19f82
AM
3796 guint *event_count = (guint*)hook_data;
3797
3798 /* Only save at LTTV_STATE_SAVE_INTERVAL */
3799 if(likely((*event_count)++ < LTTV_STATE_SAVE_INTERVAL))
3800 return FALSE;
3801 else
3802 *event_count = 0;
eed2ef37 3803
58b4e4ae 3804 LttvEvent *event = (LttvEvent *)call_data;
eed2ef37 3805
58b4e4ae 3806 LttvTraceset *traceset = lttv_trace_get_traceset(event->state->trace);
eed2ef37 3807
90e19f82 3808 LttvAttribute *saved_states_tree, *saved_state_tree;
eed2ef37 3809
90e19f82 3810 LttvAttributeValue value;
58b4e4ae
YB
3811 LttTime currentTime;
3812 guint i;
3813 currentTime = lttv_event_get_timestamp(event);
3814 int nb_trace = lttv_traceset_number(traceset);
3815 for(i = 0 ; i < nb_trace ; i++) {
eed2ef37 3816
58b4e4ae
YB
3817 LttvTrace *trace = lttv_traceset_get(traceset, i);
3818 LttvTraceState *tstate = trace->state;
3819 saved_states_tree = lttv_attribute_find_subdir(trace->a,
3820 LTTV_STATE_SAVED_STATES);
3821
3822 saved_state_tree = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
3823 value = lttv_attribute_add(saved_states_tree,
3824 lttv_attribute_get_number(saved_states_tree), LTTV_GOBJECT);
3825 *(value.v_gobject) = (GObject *)saved_state_tree;
eed2ef37 3826
eed2ef37 3827
58b4e4ae
YB
3828 value = lttv_attribute_add(saved_state_tree, LTTV_STATE_TIME, LTTV_TIME);
3829 *(value.v_time) = currentTime;
3830
3831 lttv_state_save(tstate, saved_state_tree);
3832 g_debug("Saving state at time %lu.%lu", currentTime.tv_sec,
3833 currentTime.tv_nsec);
3834
3835 *(tstate->max_time_state_recomputed_in_seek) = currentTime;
3836 }
90e19f82 3837 return FALSE;
eed2ef37 3838}
3839
14aecf75 3840static gboolean state_save_after_trace_hook(void *hook_data, void *call_data)
3841{
58b4e4ae
YB
3842#warning "Would we move max_time to traceset"
3843 LttvTrace *trace = (LttvTrace *)(call_data);
3844 LttvTraceState *tcs = trace->state;
3845 TimeInterval time_span = lttv_traceset_get_time_span_real(lttv_trace_get_traceset(trace));
14aecf75 3846
58b4e4ae 3847 *(tcs->max_time_state_recomputed_in_seek) = time_span.end_time;
90e19f82
AM
3848
3849 return FALSE;
14aecf75 3850}
58b4e4ae 3851#ifdef BABEL_CLEANUP
ae3d0f50 3852guint lttv_state_current_cpu(LttvTracefileState *tfs)
3853{
90e19f82 3854 return tfs->cpu;
ae3d0f50 3855}
3856
7a4bdb54 3857#endif //BABEL_CLEANUP
ae3d0f50 3858
eed2ef37 3859#if 0
08b1c66e 3860static gboolean block_start(void *hook_data, void *call_data)
308711e5 3861{
90e19f82 3862 LttvTracefileState *self = (LttvTracefileState *)call_data;
308711e5 3863
90e19f82 3864 LttvTracefileState *tfcs;
dbb7bb09 3865
90e19f82 3866 LttvTraceState *tcs = (LttvTraceState *)(self->parent.t_context);
308711e5 3867
90e19f82 3868 LttEventPosition *ep;
308711e5 3869
90e19f82 3870 guint i, nb_block, nb_event, nb_tracefile;
308711e5 3871
90e19f82 3872 LttTracefile *tf;
308711e5 3873
90e19f82 3874 LttvAttribute *saved_states_tree, *saved_state_tree;
308711e5 3875
90e19f82 3876 LttvAttributeValue value;
eed2ef37 3877
90e19f82 3878 ep = ltt_event_position_new();
dbb7bb09 3879
90e19f82 3880 nb_tracefile = tcs->parent.tracefiles->len;
dbb7bb09 3881
90e19f82
AM
3882 /* Count the number of events added since the last block end in any
3883 tracefile. */
308711e5 3884
90e19f82
AM
3885 for(i = 0 ; i < nb_tracefile ; i++) {
3886 tfcs =
3887 LTTV_TRACEFILE_STATE(&g_array_index(tcs->parent.tracefiles,
3888 LttvTracefileContext, i));
3889 ltt_event_position(tfcs->parent.e, ep);
3890 ltt_event_position_get(ep, &nb_block, &nb_event, &tf);
3891 tcs->nb_event += nb_event - tfcs->saved_position;
3892 tfcs->saved_position = nb_event;
3893 }
3894 g_free(ep);
3895
3896 if(tcs->nb_event >= tcs->save_interval) {
3897 saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a,
3898 LTTV_STATE_SAVED_STATES);
3899 saved_state_tree = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
3900 value = lttv_attribute_add(saved_states_tree,
3901 lttv_attribute_get_number(saved_states_tree), LTTV_GOBJECT);
3902 *(value.v_gobject) = (GObject *)saved_state_tree;
3903 value = lttv_attribute_add(saved_state_tree, LTTV_STATE_TIME, LTTV_TIME);
3904 *(value.v_time) = self->parent.timestamp;
3905 lttv_state_save(tcs, saved_state_tree);
3906 tcs->nb_event = 0;
3907 g_debug("Saving state at time %lu.%lu", self->parent.timestamp.tv_sec,
3908 self->parent.timestamp.tv_nsec);
3909 }
3910 *(tcs->max_time_state_recomputed_in_seek) = self->parent.timestamp;
3911 return FALSE;
308711e5 3912}
eed2ef37 3913#endif //0
308711e5 3914
eed2ef37 3915#if 0
08b1c66e 3916static gboolean block_end(void *hook_data, void *call_data)
3917{
90e19f82 3918 LttvTracefileState *self = (LttvTracefileState *)call_data;
08b1c66e 3919
90e19f82 3920 LttvTraceState *tcs = (LttvTraceState *)(self->parent.t_context);
08b1c66e 3921
90e19f82 3922 LttTracefile *tf;
08b1c66e 3923
90e19f82 3924 LttEventPosition *ep;
08b1c66e 3925
90e19f82 3926 guint nb_block, nb_event;
08b1c66e 3927
90e19f82
AM
3928 ep = ltt_event_position_new();
3929 ltt_event_position(self->parent.e, ep);
3930 ltt_event_position_get(ep, &nb_block, &nb_event, &tf);
3931 tcs->nb_event += nb_event - self->saved_position + 1;
3932 self->saved_position = 0;
3933 *(tcs->max_time_state_recomputed_in_seek) = self->parent.timestamp;
3934 g_free(ep);
00e74b69 3935
90e19f82 3936 return FALSE;
08b1c66e 3937}
eed2ef37 3938#endif //0
3939#if 0
308711e5 3940void lttv_state_save_add_event_hooks(LttvTracesetState *self)
3941{
90e19f82 3942 LttvTraceset *traceset = self->parent.ts;
308711e5 3943
90e19f82 3944 guint i, j, nb_trace, nb_tracefile;
308711e5 3945
90e19f82 3946 LttvTraceState *ts;
308711e5 3947
90e19f82 3948 LttvTracefileState *tfs;
308711e5 3949
90e19f82 3950 LttvTraceHook hook_start, hook_end;
308711e5 3951
90e19f82
AM
3952 nb_trace = lttv_traceset_number(traceset);
3953 for(i = 0 ; i < nb_trace ; i++) {
3954 ts = (LttvTraceState *)self->parent.traces[i];
eed2ef37 3955
90e19f82
AM
3956 lttv_trace_find_hook(ts->parent.t, "core","block_start",NULL,
3957 NULL, NULL, block_start, &hook_start);
3958 lttv_trace_find_hook(ts->parent.t, "core","block_end",NULL,
3959 NULL, NULL, block_end, &hook_end);
308711e5 3960
90e19f82 3961 nb_tracefile = ts->parent.tracefiles->len;
308711e5 3962
90e19f82
AM
3963 for(j = 0 ; j < nb_tracefile ; j++) {
3964 tfs =
3965 LTTV_TRACEFILE_STATE(&g_array_index(ts->parent.tracefiles,
3966 LttvTracefileContext, j));
3967 lttv_hooks_add(lttv_hooks_by_id_find(tfs->parent.event_by_id,
3968 hook_start.id), hook_start.h, NULL, LTTV_PRIO_STATE);
3969 lttv_hooks_add(lttv_hooks_by_id_find(tfs->parent.event_by_id,
3970 hook_end.id), hook_end.h, NULL, LTTV_PRIO_STATE);
3971 }
3972 }
eed2ef37 3973}
3974#endif //0
58b4e4ae
YB
3975
3976void lttv_state_save_add_event_hooks(LttvTraceset *traceset)
eed2ef37 3977{
eed2ef37 3978
90e19f82 3979 guint i, j, nb_trace, nb_tracefile;
eed2ef37 3980
90e19f82 3981 LttvTraceState *ts;
eed2ef37 3982
90e19f82 3983 LttvTracefileState *tfs;
eed2ef37 3984
58b4e4ae
YB
3985
3986 if(!traceset->has_precomputed_states) {
3987 guint *event_count = g_new(guint, 1);
3988
3989 *event_count = 0;
3990 lttv_hooks_add(traceset->event_hooks,
3991 state_save_event_hook,
3992 event_count,
3993 LTTV_PRIO_STATE);
3994
3995#ifdef BABEL_CLEANUP
90e19f82
AM
3996 nb_trace = lttv_traceset_number(traceset);
3997 for(i = 0 ; i < nb_trace ; i++) {
eed2ef37 3998
90e19f82
AM
3999 ts = (LttvTraceState *)self->parent.traces[i];
4000 nb_tracefile = ts->parent.tracefiles->len;
eed2ef37 4001
90e19f82 4002 if(ts->has_precomputed_states) continue;
ce05e187 4003
90e19f82
AM
4004 guint *event_count = g_new(guint, 1);
4005 *event_count = 0;
3054461a 4006
90e19f82
AM
4007 for(j = 0 ; j < nb_tracefile ; j++) {
4008 tfs =
4009 LTTV_TRACEFILE_STATE(g_array_index(ts->parent.tracefiles,
4010 LttvTracefileContext*, j));
4011 lttv_hooks_add(tfs->parent.event,
4012 state_save_event_hook,
4013 event_count,
4014 LTTV_PRIO_STATE);
4015
4016 }
4017 }
58b4e4ae
YB
4018#endif
4019 lttv_process_traceset_begin(traceset,
4020 NULL, NULL, NULL, NULL, NULL);
4021 }
eed2ef37 4022
308711e5 4023}
4024
b56b5fec 4025gint lttv_state_save_hook_add_event_hooks(void *hook_data, void *call_data)
4026{
58b4e4ae 4027 LttvTraceset *ts = (LttvTraceset*)(call_data);
b56b5fec 4028
58b4e4ae 4029 lttv_state_save_add_event_hooks(ts);
b56b5fec 4030
90e19f82 4031 return 0;
b56b5fec 4032}
58b4e4ae 4033
308711e5 4034
eed2ef37 4035#if 0
308711e5 4036void lttv_state_save_remove_event_hooks(LttvTracesetState *self)
4037{
90e19f82 4038 LttvTraceset *traceset = self->parent.ts;
308711e5 4039
90e19f82 4040 guint i, j, nb_trace, nb_tracefile;
308711e5 4041
90e19f82 4042 LttvTraceState *ts;
308711e5 4043
90e19f82 4044 LttvTracefileState *tfs;
308711e5 4045
90e19f82 4046 LttvTraceHook hook_start, hook_end;
308711e5 4047
90e19f82
AM
4048 nb_trace = lttv_traceset_number(traceset);
4049 for(i = 0 ; i < nb_trace ; i++) {
4050 ts = LTTV_TRACE_STATE(self->parent.traces[i]);
eed2ef37 4051
90e19f82
AM
4052 lttv_trace_find_hook(ts->parent.t, "core","block_start",NULL,
4053 NULL, NULL, block_start, &hook_start);
08b1c66e 4054
90e19f82
AM
4055 lttv_trace_find_hook(ts->parent.t, "core","block_end",NULL,
4056 NULL, NULL, block_end, &hook_end);
308711e5 4057
90e19f82 4058 nb_tracefile = ts->parent.tracefiles->len;
308711e5 4059
90e19f82
AM
4060 for(j = 0 ; j < nb_tracefile ; j++) {
4061 tfs =
4062 LTTV_TRACEFILE_STATE(&g_array_index(ts->parent.tracefiles,
4063 LttvTracefileContext, j));
4064 lttv_hooks_remove_data(lttv_hooks_by_id_find(
4065 tfs->parent.event_by_id, hook_start.id), hook_start.h, NULL);
4066 lttv_hooks_remove_data(lttv_hooks_by_id_find(
4067 tfs->parent.event_by_id, hook_end.id), hook_end.h, NULL);
4068 }
4069 }
308711e5 4070}
eed2ef37 4071#endif //0
58b4e4ae
YB
4072
4073void lttv_state_save_remove_event_hooks(LttvTraceset *traceset)
eed2ef37 4074{
eed2ef37 4075
90e19f82 4076 guint i, j, nb_trace, nb_tracefile;
eed2ef37 4077
90e19f82 4078 LttvTraceState *ts;
eed2ef37 4079
90e19f82 4080 LttvTracefileState *tfs;
eed2ef37 4081
90e19f82 4082 LttvHooks *after_trace = lttv_hooks_new();
58b4e4ae 4083 guint *event_count = NULL;
14aecf75 4084
90e19f82
AM
4085 lttv_hooks_add(after_trace,
4086 state_save_after_trace_hook,
4087 NULL,
4088 LTTV_PRIO_STATE);
4089
4090
58b4e4ae
YB
4091 lttv_process_traceset_end(traceset,
4092 NULL, after_trace, NULL, NULL);
eed2ef37 4093
90e19f82
AM
4094 lttv_hooks_destroy(after_trace);
4095
58b4e4ae
YB
4096 //nb_trace = lttv_traceset_number(traceset);
4097
4098 event_count = lttv_hooks_remove(traceset->event_hooks,
4099 state_save_event_hook);
4100
4101 if(event_count) g_free(event_count);
4102
4103#ifdef BABEL_CLEANUP
90e19f82 4104 for(i = 0 ; i < nb_trace ; i++) {
eed2ef37 4105
90e19f82
AM
4106 ts = (LttvTraceState *)self->parent.traces[i];
4107 nb_tracefile = ts->parent.tracefiles->len;
eed2ef37 4108
90e19f82 4109 if(ts->has_precomputed_states) continue;
ce05e187 4110
90e19f82 4111 guint *event_count = NULL;
eed2ef37 4112
90e19f82
AM
4113 for(j = 0 ; j < nb_tracefile ; j++) {
4114 tfs =
4115 LTTV_TRACEFILE_STATE(g_array_index(ts->parent.tracefiles,
4116 LttvTracefileContext*, j));
4117 event_count = lttv_hooks_remove(tfs->parent.event,
4118 state_save_event_hook);
4119 }
4120 if(event_count) g_free(event_count);
4121 }
58b4e4ae 4122#endif
eed2ef37 4123}
308711e5 4124
b56b5fec 4125gint lttv_state_save_hook_remove_event_hooks(void *hook_data, void *call_data)
4126{
58b4e4ae 4127 LttvTraceset *ts = (LttvTraceset*)(call_data);
b56b5fec 4128
58b4e4ae 4129 lttv_state_save_remove_event_hooks(ts);
b56b5fec 4130
90e19f82 4131 return 0;
b56b5fec 4132}
308711e5 4133
58b4e4ae
YB
4134
4135void lttv_state_traceset_seek_time(LttvTraceset *traceset, LttTime t)
308711e5 4136{
58b4e4ae
YB
4137 lttv_state_traceset_seek_time_closest(traceset,
4138 t);
4139 lttv_process_traceset_middle(traceset, t, G_MAXUINT,
4140 NULL);
4141}
90e19f82 4142
58b4e4ae
YB
4143void lttv_state_traceset_seek_position(LttvTraceset *traceset, LttvTracesetPosition *position)
4144{
4145 LttTime t = lttv_traceset_position_get_time(position);
4146
4147 lttv_state_traceset_seek_time_closest(traceset,
4148 t);
4149 lttv_process_traceset_middle(traceset,
4150 ltt_time_infinite,
4151 G_MAXUINT,
4152 position);
4153}
4154
4155void lttv_state_traceset_seek_time_closest(LttvTraceset *traceset, LttTime t)
4156{
90e19f82 4157 guint i, nb_trace;
308711e5 4158
90e19f82 4159 int min_pos, mid_pos, max_pos;
308711e5 4160
90e19f82 4161 guint call_rest = 0;
58b4e4ae
YB
4162 guint resto_start = 0;
4163 guint resto_at = 0;
728d0c3e 4164
90e19f82 4165 LttvAttributeValue value;
308711e5 4166
90e19f82 4167 LttvAttributeType type;
308711e5 4168
90e19f82 4169 LttvAttributeName name;
308711e5 4170
90e19f82 4171 gboolean is_named;
308711e5 4172
90e19f82 4173 LttvAttribute *saved_states_tree, *saved_state_tree, *closest_tree = NULL;
58b4e4ae
YB
4174
4175 LttTime closest_tree_time, restored_time;
c0cb4d12 4176
90e19f82
AM
4177 //g_tree_destroy(self->parent.pqueue);
4178 //self->parent.pqueue = g_tree_new(compare_tracefile);
308711e5 4179
90e19f82 4180 g_info("Entering seek_time_closest for time %lu.%lu", t.tv_sec, t.tv_nsec);
308711e5 4181
90e19f82
AM
4182 nb_trace = lttv_traceset_number(traceset);
4183 for(i = 0 ; i < nb_trace ; i++) {
2a2fa4f0 4184
58b4e4ae
YB
4185 LttvTrace *trace = lttv_traceset_get(traceset, i);
4186 LttvTraceState *tstate = trace->state;
4187
4188 if(ltt_time_compare(t, *(tstate->max_time_state_recomputed_in_seek)) < 0) {
4189 saved_states_tree = lttv_attribute_find_subdir(trace->a,
90e19f82
AM
4190 LTTV_STATE_SAVED_STATES);
4191 min_pos = -1;
dd025f91 4192
90e19f82
AM
4193 if(saved_states_tree) {
4194 max_pos = lttv_attribute_get_number(saved_states_tree) - 1;
4195 mid_pos = max_pos / 2;
4196 while(min_pos < max_pos) {
4197 type = lttv_attribute_get(saved_states_tree, mid_pos,
4198 &name, &value, &is_named);
4199 g_assert(type == LTTV_GOBJECT);
4200 saved_state_tree = *((LttvAttribute **)(value.v_gobject));
4201 type = lttv_attribute_get_by_name(saved_state_tree,
4202 LTTV_STATE_TIME, &value);
4203 g_assert(type == LTTV_TIME);
4204 if(ltt_time_compare(*(value.v_time), t) < 0) {
4205 min_pos = mid_pos;
4206 closest_tree = saved_state_tree;
58b4e4ae 4207 closest_tree_time = *(value.v_time);
90e19f82
AM
4208 }
4209 else max_pos = mid_pos - 1;
dd025f91 4210
90e19f82
AM
4211 mid_pos = (min_pos + max_pos + 1) / 2;
4212 }
4213 }
dd025f91 4214
90e19f82
AM
4215 /* restore the closest earlier saved state */
4216 if(min_pos != -1) {
58b4e4ae
YB
4217 if(ltt_time_compare(restored_time, closest_tree_time) == 0) {
4218
4219 lttv_state_restore(tstate, closest_tree);
4220
4221 restored_time = closest_tree_time;
4222 call_rest = 1;
4223 } else {
4224 g_debug("State: restored time mismatch between traces");
4225 resto_start = 1;
4226 break;
4227 }
4228
90e19f82
AM
4229 }
4230
4231 /* There is no saved state, yet we want to have it. Restart at T0 */
4232 else {
58b4e4ae
YB
4233 resto_start = 1;
4234 break;
90e19f82
AM
4235 }
4236 }
4237 /* We want to seek quickly without restoring/updating the state */
4238 else {
58b4e4ae
YB
4239 resto_at = 1;
4240 break;
90e19f82
AM
4241 }
4242 }
58b4e4ae
YB
4243
4244 if(resto_start || resto_at) {
4245 // Restore init state and seek so
4246 for(i = 0 ; i < nb_trace ; i++) {
4247
4248 LttvTrace *trace = lttv_traceset_get(traceset, i);
4249 LttvTraceState *tstate = trace->state;
4250
4251 restore_init_state(tstate);
4252 }
4253
4254 // If t > max saved state
4255 if(resto_at) {
4256 lttv_process_traceset_seek_time(traceset, t);
4257 } else if (resto_start) {
4258 // If no saved state
4259 lttv_process_traceset_seek_time(traceset, ltt_time_zero);
4260 } else {
4261 g_assert(FALSE);
4262 }
4263 g_info("NOT Calling restore");
4264
4265 } else {
4266 // Seek at checkpoint
4267 lttv_process_traceset_seek_time(traceset, restored_time);
4268
4269
4270 }
4271
4272
308711e5 4273}
58b4e4ae 4274
7a4bdb54 4275#ifdef BABEL_CLEANUP
90e19f82 4276static void traceset_state_instance_init (GTypeInstance *instance, gpointer g_class)
308711e5 4277{
4278}
4279
4280
90e19f82 4281static void traceset_state_finalize (LttvTracesetState *self)
308711e5 4282{
90e19f82
AM
4283 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))->
4284 finalize(G_OBJECT(self));
308711e5 4285}
4286
4287
90e19f82 4288static void traceset_state_class_init (LttvTracesetContextClass *klass)
308711e5 4289{
90e19f82 4290 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
308711e5 4291
90e19f82
AM
4292 gobject_class->finalize = (void (*)(GObject *self)) traceset_state_finalize;
4293 klass->init = (void (*)(LttvTracesetContext *self, LttvTraceset *ts))init;
4294 klass->fini = (void (*)(LttvTracesetContext *self))fini;
4295 klass->new_traceset_context = new_traceset_context;
4296 klass->new_trace_context = new_trace_context;
4297 klass->new_tracefile_context = new_tracefile_context;
308711e5 4298}
4299
4300
90e19f82 4301GType lttv_traceset_state_get_type(void)
308711e5 4302{
90e19f82
AM
4303 static GType type = 0;
4304 if (type == 0) {
4305 static const GTypeInfo info = {
4306 sizeof (LttvTracesetStateClass),
4307 NULL, /* base_init */
4308 NULL, /* base_finalize */
4309 (GClassInitFunc) traceset_state_class_init, /* class_init */
4310 NULL, /* class_finalize */
4311 NULL, /* class_data */
4312 sizeof (LttvTracesetState),
4313 0, /* n_preallocs */
4314 (GInstanceInitFunc) traceset_state_instance_init, /* instance_init */
4315 NULL /* value handling */
4316 };
308711e5 4317
90e19f82
AM
4318 type = g_type_register_static (LTTV_TRACESET_CONTEXT_TYPE, "LttvTracesetStateType",
4319 &info, 0);
4320 }
4321 return type;
308711e5 4322}
4323
7a4bdb54
YB
4324#endif
4325#if BABEL_CLEANUP
90e19f82 4326static void trace_state_instance_init (GTypeInstance *instance, gpointer g_class)
308711e5 4327{
4328}
4329
4330
90e19f82 4331static void trace_state_finalize (LttvTraceState *self)
308711e5 4332{
90e19f82
AM
4333 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_CONTEXT_TYPE))->
4334 finalize(G_OBJECT(self));
308711e5 4335}
4336
4337
90e19f82 4338static void trace_state_class_init (LttvTraceStateClass *klass)
308711e5 4339{
90e19f82 4340 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
308711e5 4341
90e19f82
AM
4342 gobject_class->finalize = (void (*)(GObject *self)) trace_state_finalize;
4343 klass->state_save = state_save;
4344 klass->state_restore = state_restore;
4345 klass->state_saved_free = state_saved_free;
308711e5 4346}
4347
4348
90e19f82 4349GType lttv_trace_state_get_type(void)
308711e5 4350{
90e19f82
AM
4351 static GType type = 0;
4352 if (type == 0) {
4353 static const GTypeInfo info = {
4354 sizeof (LttvTraceStateClass),
4355 NULL, /* base_init */
4356 NULL, /* base_finalize */
4357 (GClassInitFunc) trace_state_class_init, /* class_init */
4358 NULL, /* class_finalize */
4359 NULL, /* class_data */
4360 sizeof (LttvTraceState),
4361 0, /* n_preallocs */
4362 (GInstanceInitFunc) trace_state_instance_init, /* instance_init */
4363 NULL /* value handling */
4364 };
308711e5 4365
90e19f82
AM
4366 type = g_type_register_static (LTTV_TRACE_CONTEXT_TYPE,
4367 "LttvTraceStateType", &info, 0);
4368 }
4369 return type;
308711e5 4370}
4371
4372
90e19f82
AM
4373static void tracefile_state_instance_init (GTypeInstance *instance,
4374 gpointer g_class)
308711e5 4375{
4376}
4377
4378
90e19f82 4379static void tracefile_state_finalize (LttvTracefileState *self)
308711e5 4380{
90e19f82
AM
4381 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_CONTEXT_TYPE))->
4382 finalize(G_OBJECT(self));
308711e5 4383}
4384
4385
90e19f82 4386static void tracefile_state_class_init (LttvTracefileStateClass *klass)
308711e5 4387{
90e19f82 4388 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
308711e5 4389
90e19f82 4390 gobject_class->finalize = (void (*)(GObject *self)) tracefile_state_finalize;
308711e5 4391}
4392
4393
90e19f82 4394GType lttv_tracefile_state_get_type(void)
308711e5 4395{
90e19f82
AM
4396 static GType type = 0;
4397 if (type == 0) {
4398 static const GTypeInfo info = {
4399 sizeof (LttvTracefileStateClass),
4400 NULL, /* base_init */
4401 NULL, /* base_finalize */
4402 (GClassInitFunc) tracefile_state_class_init, /* class_init */
4403 NULL, /* class_finalize */
4404 NULL, /* class_data */
4405 sizeof (LttvTracefileState),
4406 0, /* n_preallocs */
4407 (GInstanceInitFunc) tracefile_state_instance_init, /* instance_init */
4408 NULL /* value handling */
4409 };
308711e5 4410
90e19f82
AM
4411 type = g_type_register_static (LTTV_TRACEFILE_CONTEXT_TYPE,
4412 "LttvTracefileStateType", &info, 0);
4413 }
4414 return type;
308711e5 4415}
4416
7a4bdb54
YB
4417#endif
4418static void module_init(void)
ffd54a90 4419{
90e19f82
AM
4420 LTTV_STATE_UNNAMED = g_quark_from_string("");
4421 LTTV_STATE_UNBRANDED = g_quark_from_string("");
4422 LTTV_STATE_MODE_UNKNOWN = g_quark_from_string("MODE_UNKNOWN");
4423 LTTV_STATE_USER_MODE = g_quark_from_string("USER_MODE");
f044974e 4424 LTTV_STATE_MAYBE_USER_MODE = g_quark_from_string("MAYBE_USER_MODE");
90e19f82 4425 LTTV_STATE_SYSCALL = g_quark_from_string("SYSCALL");
f044974e 4426 LTTV_STATE_MAYBE_SYSCALL = g_quark_from_string("MAYBE_SYSCALL");
90e19f82 4427 LTTV_STATE_TRAP = g_quark_from_string("TRAP");
f044974e 4428 LTTV_STATE_MAYBE_TRAP = g_quark_from_string("MAYBE_TRAP");
90e19f82
AM
4429 LTTV_STATE_IRQ = g_quark_from_string("IRQ");
4430 LTTV_STATE_SOFT_IRQ = g_quark_from_string("SOFTIRQ");
4431 LTTV_STATE_SUBMODE_UNKNOWN = g_quark_from_string("UNKNOWN");
4432 LTTV_STATE_SUBMODE_NONE = g_quark_from_string("NONE");
4433 LTTV_STATE_WAIT_FORK = g_quark_from_string("WAIT_FORK");
4434 LTTV_STATE_WAIT_CPU = g_quark_from_string("WAIT_CPU");
4435 LTTV_STATE_EXIT = g_quark_from_string("EXIT");
4436 LTTV_STATE_ZOMBIE = g_quark_from_string("ZOMBIE");
4437 LTTV_STATE_WAIT = g_quark_from_string("WAIT");
4438 LTTV_STATE_RUN = g_quark_from_string("RUN");
4439 LTTV_STATE_DEAD = g_quark_from_string("DEAD");
4440 LTTV_STATE_USER_THREAD = g_quark_from_string("USER_THREAD");
4441 LTTV_STATE_KERNEL_THREAD = g_quark_from_string("KERNEL_THREAD");
4442 LTTV_STATE_TRACEFILES = g_quark_from_string("tracefiles");
4443 LTTV_STATE_PROCESSES = g_quark_from_string("processes");
4444 LTTV_STATE_PROCESS = g_quark_from_string("process");
4445 LTTV_STATE_RUNNING_PROCESS = g_quark_from_string("running_process");
7a4bdb54 4446 LTTV_STATE_POSITION = g_quark_from_string("position");
90e19f82
AM
4447 LTTV_STATE_SAVED_STATES = g_quark_from_string("saved states");
4448 LTTV_STATE_SAVED_STATES_TIME = g_quark_from_string("saved states time");
4449 LTTV_STATE_TIME = g_quark_from_string("time");
4450 LTTV_STATE_HOOKS = g_quark_from_string("saved state hooks");
4451 LTTV_STATE_NAME_TABLES = g_quark_from_string("name tables");
4452 LTTV_STATE_TRACE_STATE_USE_COUNT =
4453 g_quark_from_string("trace_state_use_count");
4454 LTTV_STATE_RESOURCE_CPUS = g_quark_from_string("cpu resource states");
4455 LTTV_STATE_RESOURCE_CPUS = g_quark_from_string("cpu count");
4456 LTTV_STATE_RESOURCE_IRQS = g_quark_from_string("irq resource states");
4457 LTTV_STATE_RESOURCE_SOFT_IRQS = g_quark_from_string("soft irq resource states");
4458 LTTV_STATE_RESOURCE_TRAPS = g_quark_from_string("trap resource states");
4459 LTTV_STATE_RESOURCE_BLKDEVS = g_quark_from_string("blkdevs resource states");
4460
4461 LTT_CHANNEL_FD_STATE = g_quark_from_string("fd_state");
4462 LTT_CHANNEL_GLOBAL_STATE = g_quark_from_string("global_state");
4463 LTT_CHANNEL_IRQ_STATE = g_quark_from_string("irq_state");
4464 LTT_CHANNEL_MODULE_STATE = g_quark_from_string("module_state");
4465 LTT_CHANNEL_NETIF_STATE = g_quark_from_string("netif_state");
4466 LTT_CHANNEL_SOFTIRQ_STATE = g_quark_from_string("softirq_state");
4467 LTT_CHANNEL_SWAP_STATE = g_quark_from_string("swap_state");
4468 LTT_CHANNEL_SYSCALL_STATE = g_quark_from_string("syscall_state");
4469 LTT_CHANNEL_TASK_STATE = g_quark_from_string("task_state");
4470 LTT_CHANNEL_VM_STATE = g_quark_from_string("vm_state");
4471 LTT_CHANNEL_KPROBE_STATE = g_quark_from_string("kprobe_state");
4472 LTT_CHANNEL_FS = g_quark_from_string("fs");
4473 LTT_CHANNEL_KERNEL = g_quark_from_string("kernel");
4474 LTT_CHANNEL_MM = g_quark_from_string("mm");
4475 LTT_CHANNEL_USERSPACE = g_quark_from_string("userspace");
4476 LTT_CHANNEL_BLOCK = g_quark_from_string("block");
4477
4478 LTT_EVENT_SYSCALL_ENTRY = g_quark_from_string("syscall_entry");
4479 LTT_EVENT_SYSCALL_EXIT = g_quark_from_string("syscall_exit");
7a4bdb54
YB
4480 //LTT_EVENT_TRAP_ENTRY = g_quark_from_string("trap_entry");
4481 //LTT_EVENT_TRAP_EXIT = g_quark_from_string("trap_exit");
90e19f82
AM
4482 LTT_EVENT_PAGE_FAULT_ENTRY = g_quark_from_string("page_fault_entry");
4483 LTT_EVENT_PAGE_FAULT_EXIT = g_quark_from_string("page_fault_exit");
4484 LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY = g_quark_from_string("page_fault_nosem_entry");
4485 LTT_EVENT_PAGE_FAULT_NOSEM_EXIT = g_quark_from_string("page_fault_nosem_exit");
4486 LTT_EVENT_IRQ_ENTRY = g_quark_from_string("irq_entry");
4487 LTT_EVENT_IRQ_EXIT = g_quark_from_string("irq_exit");
4488 LTT_EVENT_SOFT_IRQ_RAISE = g_quark_from_string("softirq_raise");
4489 LTT_EVENT_SOFT_IRQ_ENTRY = g_quark_from_string("softirq_entry");
4490 LTT_EVENT_SOFT_IRQ_EXIT = g_quark_from_string("softirq_exit");
4491 LTT_EVENT_SCHED_SCHEDULE = g_quark_from_string("sched_schedule");
4492 LTT_EVENT_SCHED_TRY_WAKEUP = g_quark_from_string("sched_try_wakeup");
4493 LTT_EVENT_PROCESS_FORK = g_quark_from_string("process_fork");
4494 LTT_EVENT_KTHREAD_CREATE = g_quark_from_string("kthread_create");
4495 LTT_EVENT_PROCESS_EXIT = g_quark_from_string("process_exit");
4496 LTT_EVENT_PROCESS_FREE = g_quark_from_string("process_free");
4497 LTT_EVENT_EXEC = g_quark_from_string("exec");
4498 LTT_EVENT_PROCESS_STATE = g_quark_from_string("process_state");
4499 LTT_EVENT_STATEDUMP_END = g_quark_from_string("statedump_end");
4500 LTT_EVENT_FUNCTION_ENTRY = g_quark_from_string("function_entry");
4501 LTT_EVENT_FUNCTION_EXIT = g_quark_from_string("function_exit");
4502 LTT_EVENT_THREAD_BRAND = g_quark_from_string("thread_brand");
4503 LTT_EVENT_REQUEST_ISSUE = g_quark_from_string("_blk_request_issue");
4504 LTT_EVENT_REQUEST_COMPLETE = g_quark_from_string("_blk_request_complete");
4505 LTT_EVENT_LIST_INTERRUPT = g_quark_from_string("interrupt");
4506 LTT_EVENT_SYS_CALL_TABLE = g_quark_from_string("sys_call_table");
4507 LTT_EVENT_SOFTIRQ_VEC = g_quark_from_string("softirq_vec");
4508 LTT_EVENT_KPROBE_TABLE = g_quark_from_string("kprobe_table");
4509 LTT_EVENT_KPROBE = g_quark_from_string("kprobe");
4510 LTT_EVENT_OPEN = g_quark_from_string("open");
4511 LTT_EVENT_READ = g_quark_from_string("read");
4512 LTT_EVENT_POLL_EVENT = g_quark_from_string("poll_event");
4513
4514 LTT_FIELD_SYSCALL_ID = g_quark_from_string("syscall_id");
4515 LTT_FIELD_TRAP_ID = g_quark_from_string("trap_id");
4516 LTT_FIELD_IRQ_ID = g_quark_from_string("irq_id");
4517 LTT_FIELD_SOFT_IRQ_ID = g_quark_from_string("softirq_id");
4518 LTT_FIELD_PREV_PID = g_quark_from_string("prev_pid");
4519 LTT_FIELD_NEXT_PID = g_quark_from_string("next_pid");
4520 LTT_FIELD_PREV_STATE = g_quark_from_string("prev_state");
4521 LTT_FIELD_PARENT_PID = g_quark_from_string("parent_pid");
4522 LTT_FIELD_CHILD_PID = g_quark_from_string("child_pid");
4523 LTT_FIELD_PID = g_quark_from_string("pid");
4524 LTT_FIELD_TGID = g_quark_from_string("tgid");
4525 LTT_FIELD_CHILD_TGID = g_quark_from_string("child_tgid");
4526 LTT_FIELD_FILENAME = g_quark_from_string("filename");
4527 LTT_FIELD_NAME = g_quark_from_string("name");
4528 LTT_FIELD_TYPE = g_quark_from_string("type");
4529 LTT_FIELD_MODE = g_quark_from_string("mode");
4530 LTT_FIELD_SUBMODE = g_quark_from_string("submode");
4531 LTT_FIELD_STATUS = g_quark_from_string("status");
4532 LTT_FIELD_THIS_FN = g_quark_from_string("this_fn");
4533 LTT_FIELD_CALL_SITE = g_quark_from_string("call_site");
4534 LTT_FIELD_MAJOR = g_quark_from_string("major");
4535 LTT_FIELD_MINOR = g_quark_from_string("minor");
4536 LTT_FIELD_OPERATION = g_quark_from_string("direction");
4537 LTT_FIELD_ACTION = g_quark_from_string("action");
4538 LTT_FIELD_ID = g_quark_from_string("id");
4539 LTT_FIELD_ADDRESS = g_quark_from_string("address");
4540 LTT_FIELD_SYMBOL = g_quark_from_string("symbol");
4541 LTT_FIELD_IP = g_quark_from_string("ip");
4542 LTT_FIELD_FD = g_quark_from_string("fd");
4543 LTT_FIELD_STATE = g_quark_from_string("state");
4544 LTT_FIELD_CPU_ID = g_quark_from_string("cpu_id");
4545
4546 LTTV_CPU_UNKNOWN = g_quark_from_string("unknown");
4547 LTTV_CPU_IDLE = g_quark_from_string("idle");
4548 LTTV_CPU_BUSY = g_quark_from_string("busy");
4549 LTTV_CPU_IRQ = g_quark_from_string("irq");
4550 LTTV_CPU_SOFT_IRQ = g_quark_from_string("softirq");
4551 LTTV_CPU_TRAP = g_quark_from_string("trap");
4552
4553 LTTV_IRQ_UNKNOWN = g_quark_from_string("unknown");
4554 LTTV_IRQ_IDLE = g_quark_from_string("idle");
4555 LTTV_IRQ_BUSY = g_quark_from_string("busy");
4556
4557 LTTV_BDEV_UNKNOWN = g_quark_from_string("unknown");
4558 LTTV_BDEV_IDLE = g_quark_from_string("idle");
4559 LTTV_BDEV_BUSY_READING = g_quark_from_string("busy_reading");
4560 LTTV_BDEV_BUSY_WRITING = g_quark_from_string("busy_writing");
ffd54a90 4561}
dc877563 4562
08b1c66e 4563static void module_destroy()
ffd54a90 4564{
4565}
dc877563 4566
4567
08b1c66e 4568LTTV_MODULE("state", "State computation", \
90e19f82
AM
4569 "Update the system state, possibly saving it at intervals", \
4570 module_init, module_destroy)
08b1c66e 4571
dc877563 4572
4573
This page took 0.472922 seconds and 4 git commands to generate.