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