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