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