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