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