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