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