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