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