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