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