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