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