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