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