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