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