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