update order
[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
e8f2280c 33#define PREALLOCATED_EXECUTION_STACK 10
34
eed2ef37 35/* Facilities Quarks */
36
37GQuark
38 LTT_FACILITY_KERNEL,
f5d7967f 39 LTT_FACILITY_KERNEL_ARCH,
f4b88a7d 40 LTT_FACILITY_PROCESS,
b3fd4c02 41 LTT_FACILITY_FS,
302efbad 42 LTT_FACILITY_STATEDUMP,
43 LTT_FACILITY_USER_GENERIC;
eed2ef37 44
45/* Events Quarks */
46
47GQuark
48 LTT_EVENT_SYSCALL_ENTRY,
49 LTT_EVENT_SYSCALL_EXIT,
50 LTT_EVENT_TRAP_ENTRY,
51 LTT_EVENT_TRAP_EXIT,
52 LTT_EVENT_IRQ_ENTRY,
53 LTT_EVENT_IRQ_EXIT,
faf074a3 54 LTT_EVENT_SOFT_IRQ_ENTRY,
55 LTT_EVENT_SOFT_IRQ_EXIT,
eed2ef37 56 LTT_EVENT_SCHEDCHANGE,
57 LTT_EVENT_FORK,
7bfd7820 58 LTT_EVENT_KERNEL_THREAD,
eed2ef37 59 LTT_EVENT_EXIT,
f4b88a7d 60 LTT_EVENT_FREE,
b3fd4c02 61 LTT_EVENT_EXEC,
302efbad 62 LTT_EVENT_ENUM_PROCESS_STATE,
63 LTT_EVENT_FUNCTION_ENTRY,
7b5f6cf1 64 LTT_EVENT_FUNCTION_EXIT,
65 LTT_EVENT_THREAD_BRAND;
eed2ef37 66
67/* Fields Quarks */
68
69GQuark
70 LTT_FIELD_SYSCALL_ID,
71 LTT_FIELD_TRAP_ID,
72 LTT_FIELD_IRQ_ID,
faf074a3 73 LTT_FIELD_SOFT_IRQ_ID,
eed2ef37 74 LTT_FIELD_OUT,
75 LTT_FIELD_IN,
76 LTT_FIELD_OUT_STATE,
77 LTT_FIELD_PARENT_PID,
78 LTT_FIELD_CHILD_PID,
f4b88a7d 79 LTT_FIELD_PID,
b3fd4c02 80 LTT_FIELD_FILENAME,
81 LTT_FIELD_NAME,
e62e7f3a 82 LTT_FIELD_TYPE,
b3fd4c02 83 LTT_FIELD_MODE,
84 LTT_FIELD_SUBMODE,
302efbad 85 LTT_FIELD_STATUS,
86 LTT_FIELD_THIS_FN,
87 LTT_FIELD_CALL_SITE;
eed2ef37 88
b445142a 89LttvExecutionMode
90 LTTV_STATE_MODE_UNKNOWN,
ffd54a90 91 LTTV_STATE_USER_MODE,
92 LTTV_STATE_SYSCALL,
93 LTTV_STATE_TRAP,
faf074a3 94 LTTV_STATE_IRQ,
95 LTTV_STATE_SOFT_IRQ;
ffd54a90 96
b445142a 97LttvExecutionSubmode
98 LTTV_STATE_SUBMODE_UNKNOWN,
99 LTTV_STATE_SUBMODE_NONE;
ffd54a90 100
101LttvProcessStatus
102 LTTV_STATE_UNNAMED,
7b5f6cf1 103 LTTV_STATE_UNBRANDED,
ffd54a90 104 LTTV_STATE_WAIT_FORK,
105 LTTV_STATE_WAIT_CPU,
dbd243b1 106 LTTV_STATE_EXIT,
0828099d 107 LTTV_STATE_ZOMBIE,
ffd54a90 108 LTTV_STATE_WAIT,
791dffa6 109 LTTV_STATE_RUN,
110 LTTV_STATE_DEAD;
ffd54a90 111
e62e7f3a 112LttvProcessType
113 LTTV_STATE_USER_THREAD,
114 LTTV_STATE_KERNEL_THREAD;
115
ba576a78 116static GQuark
308711e5 117 LTTV_STATE_TRACEFILES,
118 LTTV_STATE_PROCESSES,
119 LTTV_STATE_PROCESS,
348c6ba8 120 LTTV_STATE_RUNNING_PROCESS,
308711e5 121 LTTV_STATE_EVENT,
122 LTTV_STATE_SAVED_STATES,
dbb7bb09 123 LTTV_STATE_SAVED_STATES_TIME,
308711e5 124 LTTV_STATE_TIME,
f95bc830 125 LTTV_STATE_HOOKS,
126 LTTV_STATE_NAME_TABLES,
127 LTTV_STATE_TRACE_STATE_USE_COUNT;
ba576a78 128
f95bc830 129static void create_max_time(LttvTraceState *tcs);
130
131static void get_max_time(LttvTraceState *tcs);
132
133static void free_max_time(LttvTraceState *tcs);
134
135static void create_name_tables(LttvTraceState *tcs);
136
137static void get_name_tables(LttvTraceState *tcs);
b445142a 138
139static void free_name_tables(LttvTraceState *tcs);
140
f95bc830 141static void free_saved_state(LttvTraceState *tcs);
142
308711e5 143static void lttv_state_free_process_table(GHashTable *processes);
ba576a78 144
dc877563 145
308711e5 146void lttv_state_save(LttvTraceState *self, LttvAttribute *container)
147{
148 LTTV_TRACE_STATE_GET_CLASS(self)->state_save(self, container);
149}
150
151
152void lttv_state_restore(LttvTraceState *self, LttvAttribute *container)
153{
154 LTTV_TRACE_STATE_GET_CLASS(self)->state_restore(self, container);
155}
156
157
2d262115 158void lttv_state_state_saved_free(LttvTraceState *self,
308711e5 159 LttvAttribute *container)
160{
f95bc830 161 LTTV_TRACE_STATE_GET_CLASS(self)->state_saved_free(self, container);
308711e5 162}
163
164
2a2fa4f0 165guint process_hash(gconstpointer key)
166{
7893f726 167 guint pid = ((const LttvProcessState *)key)->pid;
168 return (pid>>8 ^ pid>>4 ^ pid>>2 ^ pid) ;
2a2fa4f0 169}
170
171
1d1df11d 172/* If the hash table hash function is well distributed,
173 * the process_equal should compare different pid */
2a2fa4f0 174gboolean process_equal(gconstpointer a, gconstpointer b)
175{
00e74b69 176 const LttvProcessState *process_a, *process_b;
1d1df11d 177 gboolean ret = TRUE;
178
00e74b69 179 process_a = (const LttvProcessState *)a;
180 process_b = (const LttvProcessState *)b;
1d1df11d 181
182 if(likely(process_a->pid != process_b->pid)) ret = FALSE;
183 else if(likely(process_a->pid == 0 &&
348c6ba8 184 process_a->cpu != process_b->cpu)) ret = FALSE;
2a2fa4f0 185
1d1df11d 186 return ret;
2a2fa4f0 187}
188
6806b3c6 189static void delete_usertrace(gpointer key, gpointer value, gpointer user_data)
190{
191 g_tree_destroy((GTree*)value);
192}
193
194static void lttv_state_free_usertraces(GHashTable *usertraces)
195{
196 g_hash_table_foreach(usertraces, delete_usertrace, NULL);
197 g_hash_table_destroy(usertraces);
198}
199
200
2a2fa4f0 201
308711e5 202static void
203restore_init_state(LttvTraceState *self)
204{
348c6ba8 205 guint i, nb_cpus;
308711e5 206
207 LttvTracefileState *tfcs;
954417fa 208
209 LttTime start_time, end_time;
308711e5 210
348c6ba8 211 /* Free the process tables */
308711e5 212 if(self->processes != NULL) lttv_state_free_process_table(self->processes);
6806b3c6 213 if(self->usertraces != NULL) lttv_state_free_usertraces(self->usertraces);
2a2fa4f0 214 self->processes = g_hash_table_new(process_hash, process_equal);
6806b3c6 215 self->usertraces = g_hash_table_new(g_direct_hash, g_direct_equal);
308711e5 216 self->nb_event = 0;
217
348c6ba8 218 /* Seek time to beginning */
9ba3aaaf 219 // Mathieu : fix : don't seek traceset here : causes inconsistency in seek
220 // closest. It's the tracecontext job to seek the trace to the beginning
221 // anyway : the init state might be used at the middle of the trace as well...
222 //g_tree_destroy(self->parent.ts_context->pqueue);
223 //self->parent.ts_context->pqueue = g_tree_new(compare_tracefile);
348c6ba8 224
954417fa 225 ltt_trace_time_span_get(self->parent.t, &start_time, &end_time);
9ba3aaaf 226
227 //lttv_process_trace_seek_time(&self->parent, ltt_time_zero);
348c6ba8 228
229 nb_cpus = ltt_trace_get_num_cpu(self->parent.t);
230
231 /* Put the per cpu running_process to beginning state : process 0. */
232 for(i=0; i< nb_cpus; i++) {
233 self->running_process[i] = lttv_state_create_process(self, NULL, i, 0,
954417fa 234 LTTV_STATE_UNNAMED, &start_time);
348c6ba8 235 self->running_process[i]->state->s = LTTV_STATE_RUN;
236 self->running_process[i]->cpu = i;
237 }
238
239#if 0
eed2ef37 240 nb_tracefile = self->parent.tracefiles->len;
308711e5 241
dbb7bb09 242 for(i = 0 ; i < nb_tracefile ; i++) {
eed2ef37 243 tfcs =
cb03932a 244 LTTV_TRACEFILE_STATE(g_array_index(self->parent.tracefiles,
245 LttvTracefileContext*, i));
d3e01c7a 246 ltt_trace_time_span_get(self->parent.t, &tfcs->parent.timestamp, NULL);
eed2ef37 247// tfcs->saved_position = 0;
2a2fa4f0 248 tfcs->process = lttv_state_create_process(tfcs, NULL,0);
249 tfcs->process->state->s = LTTV_STATE_RUN;
250 tfcs->process->last_cpu = tfcs->cpu_name;
2c82c4dc 251 tfcs->process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfcs)->tf);
308711e5 252 }
348c6ba8 253#endif //0
308711e5 254}
255
348c6ba8 256//static LttTime time_zero = {0,0};
308711e5 257
6806b3c6 258static gint compare_usertraces(gconstpointer a, gconstpointer b,
259 gpointer user_data)
260{
261 const LttTime *t1 = (const LttTime *)a;
262 const LttTime *t2 = (const LttTime *)b;
263
264 return ltt_time_compare(*t1, *t2);
265}
266
267static void free_usertrace_key(gpointer data)
268{
269 g_free(data);
270}
271
dc877563 272static void
273init(LttvTracesetState *self, LttvTraceset *ts)
274{
dbb7bb09 275 guint i, j, nb_trace, nb_tracefile;
dc877563 276
ffd54a90 277 LttvTraceContext *tc;
dc877563 278
ffd54a90 279 LttvTraceState *tcs;
280
ffd54a90 281 LttvTracefileState *tfcs;
3d27549e 282
dbb7bb09 283 LttvAttributeValue v;
284
b445142a 285 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))->
286 init((LttvTracesetContext *)self, ts);
dc877563 287
288 nb_trace = lttv_traceset_number(ts);
289 for(i = 0 ; i < nb_trace ; i++) {
b445142a 290 tc = self->parent.traces[i];
021eeb41 291 tcs = LTTV_TRACE_STATE(tc);
eed2ef37 292 tcs->save_interval = LTTV_STATE_SAVE_INTERVAL;
f95bc830 293 lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_TRACE_STATE_USE_COUNT,
294 LTTV_UINT, &v);
295 (*v.v_uint)++;
dbb7bb09 296
f95bc830 297 if(*(v.v_uint) == 1) {
298 create_name_tables(tcs);
299 create_max_time(tcs);
300 }
301 get_name_tables(tcs);
302 get_max_time(tcs);
dc877563 303
eed2ef37 304 nb_tracefile = tc->tracefiles->len;
ae3d0f50 305 tcs->processes = NULL;
6806b3c6 306 tcs->usertraces = NULL;
ae3d0f50 307 tcs->running_process = g_new(LttvProcessState*,
308 ltt_trace_get_num_cpu(tc->t));
309 restore_init_state(tcs);
dc877563 310 for(j = 0 ; j < nb_tracefile ; j++) {
eed2ef37 311 tfcs =
cb03932a 312 LTTV_TRACEFILE_STATE(g_array_index(tc->tracefiles,
313 LttvTracefileContext*, j));
348c6ba8 314 tfcs->tracefile_name = ltt_tracefile_name(tfcs->parent.tf);
ae3d0f50 315 tfcs->cpu = ltt_tracefile_cpu(tfcs->parent.tf);
6806b3c6 316#if 0
ae3d0f50 317 if(ltt_tracefile_tid(tfcs->parent.tf) != 0) {
318 /* It's a Usertrace */
319 LttvProcessState *process;
320 LttTime timestamp =
321 ltt_interpolate_time_from_tsc(tfcs->parent.tf,
322 ltt_tracefile_creation(tfcs->parent.tf));
323 process = lttv_state_find_process_or_create(
324 tcs,
325 0, ltt_tracefile_tid(tfcs->parent.tf),
326 &timestamp);
327 process->usertrace = tfcs;
328 }
dc877563 329 }
6806b3c6 330#endif //0
331 if(ltt_tracefile_tid(tfcs->parent.tf) != 0) {
332 /* It's a Usertrace */
333 guint tid = ltt_tracefile_tid(tfcs->parent.tf);
334 GTree *usertrace_tree = (GTree*)g_hash_table_lookup(tcs->usertraces,
335 (gconstpointer)tid);
336 if(!usertrace_tree) {
337 usertrace_tree = g_tree_new_full(compare_usertraces,
338 NULL, free_usertrace_key, NULL);
339 g_hash_table_insert(tcs->usertraces,
340 (gpointer)tid, usertrace_tree);
341 }
342 LttTime *timestamp = g_new(LttTime, 1);
343 *timestamp = ltt_interpolate_time_from_tsc(tfcs->parent.tf,
344 ltt_tracefile_creation(tfcs->parent.tf));
345 g_tree_insert(usertrace_tree, timestamp, tfcs);
346 }
347 }
348
dc877563 349 }
350}
351
dc877563 352static void
353fini(LttvTracesetState *self)
354{
00e74b69 355 guint i, nb_trace;
dc877563 356
ffd54a90 357 LttvTraceState *tcs;
dc877563 358
ffd54a90 359 LttvTracefileState *tfcs;
dc877563 360
f95bc830 361 LttvAttributeValue v;
362
ffd54a90 363 nb_trace = lttv_traceset_number(LTTV_TRACESET_CONTEXT(self)->ts);
dc877563 364 for(i = 0 ; i < nb_trace ; i++) {
ffd54a90 365 tcs = (LttvTraceState *)(LTTV_TRACESET_CONTEXT(self)->traces[i]);
f95bc830 366 lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_TRACE_STATE_USE_COUNT,
367 LTTV_UINT, &v);
00e74b69 368
369 g_assert(*(v.v_uint) != 0);
f95bc830 370 (*v.v_uint)--;
371
f95bc830 372 if(*(v.v_uint) == 0) {
373 free_name_tables(tcs);
374 free_max_time(tcs);
375 free_saved_state(tcs);
376 }
348c6ba8 377 g_free(tcs->running_process);
378 tcs->running_process = NULL;
308711e5 379 lttv_state_free_process_table(tcs->processes);
6806b3c6 380 lttv_state_free_usertraces(tcs->usertraces);
308711e5 381 tcs->processes = NULL;
6806b3c6 382 tcs->usertraces = NULL;
dc877563 383 }
b445142a 384 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))->
385 fini((LttvTracesetContext *)self);
dc877563 386}
387
388
c432246e 389static LttvTracesetContext *
dc877563 390new_traceset_context(LttvTracesetContext *self)
391{
ffd54a90 392 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATE_TYPE, NULL));
dc877563 393}
394
395
c432246e 396static LttvTraceContext *
dc877563 397new_trace_context(LttvTracesetContext *self)
398{
ffd54a90 399 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATE_TYPE, NULL));
dc877563 400}
401
402
c432246e 403static LttvTracefileContext *
dc877563 404new_tracefile_context(LttvTracesetContext *self)
405{
ffd54a90 406 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATE_TYPE, NULL));
407}
408
409
dbb7bb09 410/* Write the process state of the trace */
411
412static void write_process_state(gpointer key, gpointer value,
413 gpointer user_data)
414{
415 LttvProcessState *process;
416
417 LttvExecutionState *es;
418
419 FILE *fp = (FILE *)user_data;
420
421 guint i;
422
423 process = (LttvProcessState *)value;
424 fprintf(fp,
7b5f6cf1 425" <PROCESS CORE=%p PID=%u PPID=%u TYPE=\"%s\"CTIME_S=%lu CTIME_NS=%lu NAME=\"%s\" BRAND=\"%s\" CPU=\"%u\">\n",
e62e7f3a 426 process, process->pid, process->ppid, g_quark_to_string(process->type),
427 process->creation_time.tv_sec,
dbb7bb09 428 process->creation_time.tv_nsec, g_quark_to_string(process->name),
7b5f6cf1 429 g_quark_to_string(process->brand),
348c6ba8 430 process->cpu);
dbb7bb09 431
432 for(i = 0 ; i < process->execution_stack->len; i++) {
433 es = &g_array_index(process->execution_stack, LttvExecutionState, i);
434 fprintf(fp, " <ES MODE=\"%s\" SUBMODE=\"%s\" ENTRY_S=%lu ENTRY_NS=%lu",
435 g_quark_to_string(es->t), g_quark_to_string(es->n),
436 es->entry.tv_sec, es->entry.tv_nsec);
437 fprintf(fp, " CHANGE_S=%lu CHANGE_NS=%lu STATUS=\"%s\"/>\n",
438 es->change.tv_sec, es->change.tv_nsec, g_quark_to_string(es->s));
439 }
440 fprintf(fp, " </PROCESS>\n");
441}
442
443
444void lttv_state_write(LttvTraceState *self, LttTime t, FILE *fp)
445{
eed2ef37 446 guint i, nb_tracefile, nb_block, offset;
447 guint64 tsc;
dbb7bb09 448
449 LttvTracefileState *tfcs;
450
451 LttTracefile *tf;
452
453 LttEventPosition *ep;
454
348c6ba8 455 guint nb_cpus;
456
dbb7bb09 457 ep = ltt_event_position_new();
458
459 fprintf(fp,"<PROCESS_STATE TIME_S=%lu TIME_NS=%lu>\n", t.tv_sec, t.tv_nsec);
460
461 g_hash_table_foreach(self->processes, write_process_state, fp);
348c6ba8 462
463 nb_cpus = ltt_trace_get_num_cpu(self->parent.t);
464 for(i=0;i<nb_cpus;i++) {
465 fprintf(fp,"<CPU NUM=%u RUNNING_PROCESS=%u>\n",
466 i, self->running_process[i]->pid);
467 }
dbb7bb09 468
eed2ef37 469 nb_tracefile = self->parent.tracefiles->len;
dbb7bb09 470
471 for(i = 0 ; i < nb_tracefile ; i++) {
eed2ef37 472 tfcs =
cb03932a 473 LTTV_TRACEFILE_STATE(g_array_index(self->parent.tracefiles,
474 LttvTracefileContext*, i));
348c6ba8 475 fprintf(fp, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
476 tfcs->parent.timestamp.tv_sec,
08b1c66e 477 tfcs->parent.timestamp.tv_nsec);
eed2ef37 478 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.tf);
479 if(e == NULL) fprintf(fp,"/>\n");
dbb7bb09 480 else {
eed2ef37 481 ltt_event_position(e, ep);
482 ltt_event_position_get(ep, &tf, &nb_block, &offset, &tsc);
27304273 483 fprintf(fp, " BLOCK=%u OFFSET=%u TSC=%llu/>\n", nb_block, offset,
eed2ef37 484 tsc);
dbb7bb09 485 }
486 }
487 g_free(ep);
488 fprintf(fp,"</PROCESS_STATE>");
489}
490
491
492/* Copy each process from an existing hash table to a new one */
493
308711e5 494static void copy_process_state(gpointer key, gpointer value,gpointer user_data)
ffd54a90 495{
308711e5 496 LttvProcessState *process, *new_process;
ffd54a90 497
308711e5 498 GHashTable *new_processes = (GHashTable *)user_data;
ffd54a90 499
308711e5 500 guint i;
501
502 process = (LttvProcessState *)value;
503 new_process = g_new(LttvProcessState, 1);
504 *new_process = *process;
e8f2280c 505 new_process->execution_stack = g_array_sized_new(FALSE, FALSE,
506 sizeof(LttvExecutionState), PREALLOCATED_EXECUTION_STACK);
e05fc742 507 new_process->execution_stack =
508 g_array_set_size(new_process->execution_stack,
509 process->execution_stack->len);
308711e5 510 for(i = 0 ; i < process->execution_stack->len; i++) {
511 g_array_index(new_process->execution_stack, LttvExecutionState, i) =
512 g_array_index(process->execution_stack, LttvExecutionState, i);
513 }
514 new_process->state = &g_array_index(new_process->execution_stack,
515 LttvExecutionState, new_process->execution_stack->len - 1);
302efbad 516 new_process->user_stack = g_array_sized_new(FALSE, FALSE,
517 sizeof(guint64), 0);
518 new_process->user_stack =
519 g_array_set_size(new_process->user_stack,
520 process->user_stack->len);
521 for(i = 0 ; i < process->user_stack->len; i++) {
522 g_array_index(new_process->user_stack, guint64, i) =
523 g_array_index(process->user_stack, guint64, i);
524 }
052a984f 525 new_process->current_function = process->current_function;
2a2fa4f0 526 g_hash_table_insert(new_processes, new_process, new_process);
ffd54a90 527}
528
529
308711e5 530static GHashTable *lttv_state_copy_process_table(GHashTable *processes)
ffd54a90 531{
2a2fa4f0 532 GHashTable *new_processes = g_hash_table_new(process_hash, process_equal);
ffd54a90 533
308711e5 534 g_hash_table_foreach(processes, copy_process_state, new_processes);
535 return new_processes;
dc877563 536}
537
538
308711e5 539/* The saved state for each trace contains a member "processes", which
540 stores a copy of the process table, and a member "tracefiles" with
541 one entry per tracefile. Each tracefile has a "process" member pointing
542 to the current process and a "position" member storing the tracefile
543 position (needed to seek to the current "next" event. */
544
545static void state_save(LttvTraceState *self, LttvAttribute *container)
dc877563 546{
348c6ba8 547 guint i, nb_tracefile, nb_cpus;
dc877563 548
308711e5 549 LttvTracefileState *tfcs;
550
551 LttvAttribute *tracefiles_tree, *tracefile_tree;
348c6ba8 552
553 guint *running_process;
308711e5 554
555 LttvAttributeType type;
556
557 LttvAttributeValue value;
558
559 LttvAttributeName name;
560
561 LttEventPosition *ep;
562
563 tracefiles_tree = lttv_attribute_find_subdir(container,
564 LTTV_STATE_TRACEFILES);
565
566 value = lttv_attribute_add(container, LTTV_STATE_PROCESSES,
567 LTTV_POINTER);
568 *(value.v_pointer) = lttv_state_copy_process_table(self->processes);
569
348c6ba8 570 /* Add the currently running processes array */
571 nb_cpus = ltt_trace_get_num_cpu(self->parent.t);
572 running_process = g_new(guint, nb_cpus);
573 for(i=0;i<nb_cpus;i++) {
574 running_process[i] = self->running_process[i]->pid;
575 }
576 value = lttv_attribute_add(container, LTTV_STATE_RUNNING_PROCESS,
577 LTTV_POINTER);
578 *(value.v_pointer) = running_process;
728d0c3e 579
580 g_info("State save");
348c6ba8 581
eed2ef37 582 nb_tracefile = self->parent.tracefiles->len;
308711e5 583
584 for(i = 0 ; i < nb_tracefile ; i++) {
eed2ef37 585 tfcs =
cb03932a 586 LTTV_TRACEFILE_STATE(g_array_index(self->parent.tracefiles,
587 LttvTracefileContext*, i));
308711e5 588 tracefile_tree = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
589 value = lttv_attribute_add(tracefiles_tree, i,
590 LTTV_GOBJECT);
591 *(value.v_gobject) = (GObject *)tracefile_tree;
348c6ba8 592#if 0
308711e5 593 value = lttv_attribute_add(tracefile_tree, LTTV_STATE_PROCESS,
594 LTTV_UINT);
595 *(value.v_uint) = tfcs->process->pid;
348c6ba8 596#endif //0
308711e5 597 value = lttv_attribute_add(tracefile_tree, LTTV_STATE_EVENT,
598 LTTV_POINTER);
3054461a 599 /* Only save the position if the tfs has not infinite time. */
600 //if(!g_tree_lookup(self->parent.ts_context->pqueue, &tfcs->parent)
601 // && current_tfcs != tfcs) {
602 if(ltt_time_compare(tfcs->parent.timestamp, ltt_time_infinite) == 0) {
1986f254 603 *(value.v_pointer) = NULL;
604 } else {
605 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.tf);
a5dcde2f 606 ep = ltt_event_position_new();
eed2ef37 607 ltt_event_position(e, ep);
308711e5 608 *(value.v_pointer) = ep;
08b1c66e 609
eed2ef37 610 guint nb_block, offset;
611 guint64 tsc;
08b1c66e 612 LttTracefile *tf;
eed2ef37 613 ltt_event_position_get(ep, &tf, &nb_block, &offset, &tsc);
728d0c3e 614 g_info("Block %u offset %u tsc %llu time %lu.%lu", nb_block, offset,
eed2ef37 615 tsc,
08b1c66e 616 tfcs->parent.timestamp.tv_sec, tfcs->parent.timestamp.tv_nsec);
308711e5 617 }
dc877563 618 }
dc877563 619}
620
621
308711e5 622static void state_restore(LttvTraceState *self, LttvAttribute *container)
dc877563 623{
348c6ba8 624 guint i, nb_tracefile, pid, nb_cpus;
dc877563 625
308711e5 626 LttvTracefileState *tfcs;
dc877563 627
308711e5 628 LttvAttribute *tracefiles_tree, *tracefile_tree;
dc877563 629
348c6ba8 630 guint *running_process;
631
308711e5 632 LttvAttributeType type;
dc877563 633
308711e5 634 LttvAttributeValue value;
dc877563 635
308711e5 636 LttvAttributeName name;
dc877563 637
c0cb4d12 638 gboolean is_named;
639
308711e5 640 LttEventPosition *ep;
dc877563 641
27304273 642 LttvTracesetContext *tsc = self->parent.ts_context;
643
308711e5 644 tracefiles_tree = lttv_attribute_find_subdir(container,
645 LTTV_STATE_TRACEFILES);
dc877563 646
308711e5 647 type = lttv_attribute_get_by_name(container, LTTV_STATE_PROCESSES,
648 &value);
649 g_assert(type == LTTV_POINTER);
650 lttv_state_free_process_table(self->processes);
651 self->processes = lttv_state_copy_process_table(*(value.v_pointer));
652
348c6ba8 653 /* Add the currently running processes array */
654 nb_cpus = ltt_trace_get_num_cpu(self->parent.t);
655 type = lttv_attribute_get_by_name(container, LTTV_STATE_RUNNING_PROCESS,
656 &value);
657 g_assert(type == LTTV_POINTER);
658 running_process = *(value.v_pointer);
659 for(i=0;i<nb_cpus;i++) {
660 pid = running_process[i];
661 self->running_process[i] = lttv_state_find_process(self, i, pid);
662 g_assert(self->running_process[i] != NULL);
663 }
664
665
eed2ef37 666 nb_tracefile = self->parent.tracefiles->len;
308711e5 667
d448fce2 668 //g_tree_destroy(tsc->pqueue);
669 //tsc->pqueue = g_tree_new(compare_tracefile);
e7f5e89d 670
308711e5 671 for(i = 0 ; i < nb_tracefile ; i++) {
eed2ef37 672 tfcs =
cb03932a 673 LTTV_TRACEFILE_STATE(g_array_index(self->parent.tracefiles,
674 LttvTracefileContext*, i));
c0cb4d12 675 type = lttv_attribute_get(tracefiles_tree, i, &name, &value, &is_named);
308711e5 676 g_assert(type == LTTV_GOBJECT);
677 tracefile_tree = *((LttvAttribute **)(value.v_gobject));
348c6ba8 678#if 0
308711e5 679 type = lttv_attribute_get_by_name(tracefile_tree, LTTV_STATE_PROCESS,
680 &value);
681 g_assert(type == LTTV_UINT);
2a2fa4f0 682 pid = *(value.v_uint);
683 tfcs->process = lttv_state_find_process_or_create(tfcs, pid);
348c6ba8 684#endif //0
308711e5 685 type = lttv_attribute_get_by_name(tracefile_tree, LTTV_STATE_EVENT,
686 &value);
687 g_assert(type == LTTV_POINTER);
e7f5e89d 688 //g_assert(*(value.v_pointer) != NULL);
eed2ef37 689 ep = *(value.v_pointer);
690 g_assert(tfcs->parent.t_context != NULL);
27304273 691
27304273 692 LttvTracefileContext *tfc = LTTV_TRACEFILE_CONTEXT(tfcs);
d448fce2 693 g_tree_remove(tsc->pqueue, tfc);
27304273 694
1986f254 695 if(ep != NULL) {
696 g_assert(ltt_tracefile_seek_position(tfc->tf, ep) == 0);
697 tfc->timestamp = ltt_event_time(ltt_tracefile_get_event(tfc->tf));
e7f5e89d 698 g_assert(ltt_time_compare(tfc->timestamp, ltt_time_infinite) != 0);
1986f254 699 g_tree_insert(tsc->pqueue, tfc, tfc);
728d0c3e 700 g_info("Restoring state for a tf at time %lu.%lu", tfc->timestamp.tv_sec, tfc->timestamp.tv_nsec);
1986f254 701 } else {
702 tfc->timestamp = ltt_time_infinite;
703 }
dc877563 704 }
dc877563 705}
706
707
308711e5 708static void state_saved_free(LttvTraceState *self, LttvAttribute *container)
dc877563 709{
348c6ba8 710 guint i, nb_tracefile, nb_cpus;
dc877563 711
308711e5 712 LttvTracefileState *tfcs;
dc877563 713
308711e5 714 LttvAttribute *tracefiles_tree, *tracefile_tree;
dc877563 715
348c6ba8 716 guint *running_process;
717
308711e5 718 LttvAttributeType type;
dc877563 719
308711e5 720 LttvAttributeValue value;
dc877563 721
308711e5 722 LttvAttributeName name;
dc877563 723
c0cb4d12 724 gboolean is_named;
725
308711e5 726 LttEventPosition *ep;
dc877563 727
308711e5 728 tracefiles_tree = lttv_attribute_find_subdir(container,
729 LTTV_STATE_TRACEFILES);
c47a6dc6 730 g_object_ref(G_OBJECT(tracefiles_tree));
308711e5 731 lttv_attribute_remove_by_name(container, LTTV_STATE_TRACEFILES);
dc877563 732
308711e5 733 type = lttv_attribute_get_by_name(container, LTTV_STATE_PROCESSES,
734 &value);
735 g_assert(type == LTTV_POINTER);
736 lttv_state_free_process_table(*(value.v_pointer));
737 *(value.v_pointer) = NULL;
738 lttv_attribute_remove_by_name(container, LTTV_STATE_PROCESSES);
739
348c6ba8 740 /* Free running processes array */
741 nb_cpus = ltt_trace_get_num_cpu(self->parent.t);
728d0c3e 742 type = lttv_attribute_get_by_name(container, LTTV_STATE_RUNNING_PROCESS,
348c6ba8 743 &value);
744 g_assert(type == LTTV_POINTER);
745 running_process = *(value.v_pointer);
746 g_free(running_process);
747
eed2ef37 748 nb_tracefile = self->parent.tracefiles->len;
308711e5 749
750 for(i = 0 ; i < nb_tracefile ; i++) {
eed2ef37 751 tfcs =
cb03932a 752 LTTV_TRACEFILE_STATE(g_array_index(self->parent.tracefiles,
753 LttvTracefileContext*, i));
c0cb4d12 754 type = lttv_attribute_get(tracefiles_tree, i, &name, &value, &is_named);
308711e5 755 g_assert(type == LTTV_GOBJECT);
756 tracefile_tree = *((LttvAttribute **)(value.v_gobject));
757
758 type = lttv_attribute_get_by_name(tracefile_tree, LTTV_STATE_EVENT,
759 &value);
760 g_assert(type == LTTV_POINTER);
761 if(*(value.v_pointer) != NULL) g_free(*(value.v_pointer));
dc877563 762 }
c47a6dc6 763 g_object_unref(G_OBJECT(tracefiles_tree));
dc877563 764}
765
766
f95bc830 767static void free_saved_state(LttvTraceState *self)
768{
769 guint i, nb;
770
771 LttvAttributeType type;
772
773 LttvAttributeValue value;
774
775 LttvAttributeName name;
776
c0cb4d12 777 gboolean is_named;
778
f95bc830 779 LttvAttribute *saved_states;
780
781 saved_states = lttv_attribute_find_subdir(self->parent.t_a,
782 LTTV_STATE_SAVED_STATES);
783
784 nb = lttv_attribute_get_number(saved_states);
785 for(i = 0 ; i < nb ; i++) {
c0cb4d12 786 type = lttv_attribute_get(saved_states, i, &name, &value, &is_named);
f95bc830 787 g_assert(type == LTTV_GOBJECT);
788 state_saved_free(self, *((LttvAttribute **)value.v_gobject));
789 }
790
791 lttv_attribute_remove_by_name(self->parent.t_a, LTTV_STATE_SAVED_STATES);
f95bc830 792}
793
794
795static void
796create_max_time(LttvTraceState *tcs)
797{
798 LttvAttributeValue v;
799
800 lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_SAVED_STATES_TIME,
801 LTTV_POINTER, &v);
802 g_assert(*(v.v_pointer) == NULL);
803 *(v.v_pointer) = g_new(LttTime,1);
348c6ba8 804 *((LttTime *)*(v.v_pointer)) = ltt_time_zero;
f95bc830 805}
806
807
808static void
809get_max_time(LttvTraceState *tcs)
810{
811 LttvAttributeValue v;
812
813 lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_SAVED_STATES_TIME,
814 LTTV_POINTER, &v);
815 g_assert(*(v.v_pointer) != NULL);
816 tcs->max_time_state_recomputed_in_seek = (LttTime *)*(v.v_pointer);
817}
818
819
820static void
821free_max_time(LttvTraceState *tcs)
822{
823 LttvAttributeValue v;
824
825 lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_SAVED_STATES_TIME,
826 LTTV_POINTER, &v);
827 g_free(*(v.v_pointer));
828 *(v.v_pointer) = NULL;
829}
830
831
832typedef struct _LttvNameTables {
eed2ef37 833 // FIXME GQuark *eventtype_names;
f95bc830 834 GQuark *syscall_names;
5e96e7e3 835 guint nb_syscalls;
f95bc830 836 GQuark *trap_names;
5e96e7e3 837 guint nb_traps;
f95bc830 838 GQuark *irq_names;
faf074a3 839 GQuark *soft_irq_names;
f95bc830 840} LttvNameTables;
841
842
b445142a 843static void
f95bc830 844create_name_tables(LttvTraceState *tcs)
b445142a 845{
846 int i, nb;
dc877563 847
eed2ef37 848 GQuark f_name, e_name;
849
021eeb41 850 LttvTraceHook h;
dc877563 851
eed2ef37 852 LttvTraceHookByFacility *thf;
b445142a 853
854 LttEventType *et;
855
856 LttType *t;
857
858 GString *fe_name = g_string_new("");
859
f95bc830 860 LttvNameTables *name_tables = g_new(LttvNameTables, 1);
861
862 LttvAttributeValue v;
863
864 lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_NAME_TABLES,
865 LTTV_POINTER, &v);
866 g_assert(*(v.v_pointer) == NULL);
867 *(v.v_pointer) = name_tables;
eed2ef37 868#if 0 // Use iteration over the facilities_by_name and then list all event
869 // types of each facility
b445142a 870 nb = ltt_trace_eventtype_number(tcs->parent.t);
f95bc830 871 name_tables->eventtype_names = g_new(GQuark, nb);
b445142a 872 for(i = 0 ; i < nb ; i++) {
873 et = ltt_trace_eventtype_get(tcs->parent.t, i);
874 e_name = ltt_eventtype_name(et);
875 f_name = ltt_facility_name(ltt_eventtype_facility(et));
876 g_string_printf(fe_name, "%s.%s", f_name, e_name);
f95bc830 877 name_tables->eventtype_names[i] = g_quark_from_string(fe_name->str);
b445142a 878 }
eed2ef37 879#endif //0
285468d4 880 if(!lttv_trace_find_hook(tcs->parent.t,
f5d7967f 881 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_ENTRY,
eed2ef37 882 LTT_FIELD_SYSCALL_ID, 0, 0,
285468d4 883 NULL, NULL, &h)) {
884
885 thf = lttv_trace_hook_get_first(&h);
886
887 t = ltt_field_type(thf->f1);
888 nb = ltt_type_element_number(t);
889
890 lttv_trace_hook_destroy(&h);
891
892 name_tables->syscall_names = g_new(GQuark, nb);
893 name_tables->nb_syscalls = nb;
894
895 for(i = 0 ; i < nb ; i++) {
896 name_tables->syscall_names[i] = ltt_enum_string_get(t, i);
897 }
898
899 //name_tables->syscall_names = g_new(GQuark, 256);
900 //for(i = 0 ; i < 256 ; i++) {
901 // g_string_printf(fe_name, "syscall %d", i);
902 // name_tables->syscall_names[i] = g_quark_from_string(fe_name->str);
903 //}
904 } else {
905 name_tables->syscall_names = NULL;
906 name_tables->nb_syscalls = 0;
907 }
908
909 if(!lttv_trace_find_hook(tcs->parent.t, LTT_FACILITY_KERNEL,
eed2ef37 910 LTT_EVENT_TRAP_ENTRY,
911 LTT_FIELD_TRAP_ID, 0, 0,
285468d4 912 NULL, NULL, &h)) {
eed2ef37 913
285468d4 914 thf = lttv_trace_hook_get_first(&h);
eed2ef37 915
285468d4 916 t = ltt_field_type(thf->f1);
917 //nb = ltt_type_element_number(t);
b445142a 918
285468d4 919 lttv_trace_hook_destroy(&h);
eed2ef37 920
285468d4 921 /*
922 name_tables->trap_names = g_new(GQuark, nb);
923 for(i = 0 ; i < nb ; i++) {
924 name_tables->trap_names[i] = g_quark_from_string(
925 ltt_enum_string_get(t, i));
926 }
927 */
5e96e7e3 928 name_tables->nb_traps = 256;
285468d4 929 name_tables->trap_names = g_new(GQuark, 256);
930 for(i = 0 ; i < 256 ; i++) {
931 g_string_printf(fe_name, "trap %d", i);
932 name_tables->trap_names[i] = g_quark_from_string(fe_name->str);
933 }
934 } else {
935 name_tables->trap_names = NULL;
5e96e7e3 936 name_tables->nb_traps = 0;
285468d4 937 }
b445142a 938
285468d4 939 if(!lttv_trace_find_hook(tcs->parent.t,
eed2ef37 940 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
941 LTT_FIELD_IRQ_ID, 0, 0,
285468d4 942 NULL, NULL, &h)) {
943
944 thf = lttv_trace_hook_get_first(&h);
945
946 t = ltt_field_type(thf->f1);
947 //nb = ltt_type_element_number(t);
948
949 lttv_trace_hook_destroy(&h);
950
951 /*
952 name_tables->irq_names = g_new(GQuark, nb);
953 for(i = 0 ; i < nb ; i++) {
954 name_tables->irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
955 }
956 */
957
958 name_tables->irq_names = g_new(GQuark, 256);
959 for(i = 0 ; i < 256 ; i++) {
960 g_string_printf(fe_name, "irq %d", i);
961 name_tables->irq_names[i] = g_quark_from_string(fe_name->str);
962 }
963 } else {
964 name_tables->irq_names = NULL;
965 }
faf074a3 966 /*
967 name_tables->soft_irq_names = g_new(GQuark, nb);
968 for(i = 0 ; i < nb ; i++) {
969 name_tables->soft_irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
970 }
971 */
972
973 name_tables->soft_irq_names = g_new(GQuark, 256);
974 for(i = 0 ; i < 256 ; i++) {
975 g_string_printf(fe_name, "softirq %d", i);
976 name_tables->soft_irq_names[i] = g_quark_from_string(fe_name->str);
977 }
978
979
b445142a 980 g_string_free(fe_name, TRUE);
981}
982
983
f95bc830 984static void
985get_name_tables(LttvTraceState *tcs)
986{
987 LttvNameTables *name_tables;
988
989 LttvAttributeValue v;
990
991 lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_NAME_TABLES,
992 LTTV_POINTER, &v);
993 g_assert(*(v.v_pointer) != NULL);
994 name_tables = (LttvNameTables *)*(v.v_pointer);
eed2ef37 995 //tcs->eventtype_names = name_tables->eventtype_names;
f95bc830 996 tcs->syscall_names = name_tables->syscall_names;
7cd289b0 997 tcs->nb_syscalls = name_tables->nb_syscalls;
f95bc830 998 tcs->trap_names = name_tables->trap_names;
5e96e7e3 999 tcs->nb_traps = name_tables->nb_traps;
f95bc830 1000 tcs->irq_names = name_tables->irq_names;
faf074a3 1001 tcs->soft_irq_names = name_tables->soft_irq_names;
f95bc830 1002}
1003
1004
b445142a 1005static void
1006free_name_tables(LttvTraceState *tcs)
1007{
f95bc830 1008 LttvNameTables *name_tables;
1009
1010 LttvAttributeValue v;
1011
1012 lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_NAME_TABLES,
1013 LTTV_POINTER, &v);
1014 name_tables = (LttvNameTables *)*(v.v_pointer);
1015 *(v.v_pointer) = NULL;
1016
eed2ef37 1017 // g_free(name_tables->eventtype_names);
285468d4 1018 if(name_tables->syscall_names) g_free(name_tables->syscall_names);
1019 if(name_tables->trap_names) g_free(name_tables->trap_names);
1020 if(name_tables->irq_names) g_free(name_tables->irq_names);
1021 if(name_tables->soft_irq_names) g_free(name_tables->soft_irq_names);
1022 if(name_tables) g_free(name_tables);
b445142a 1023}
dc877563 1024
15b3d537 1025#ifdef HASH_TABLE_DEBUG
1026
1027static void test_process(gpointer key, gpointer value, gpointer user_data)
1028{
1029 LttvProcessState *process = (LttvProcessState *)value;
1030
1031 /* Test for process corruption */
1032 guint stack_len = process->execution_stack->len;
1033}
1034
1035static void hash_table_check(GHashTable *table)
1036{
1037 g_hash_table_foreach(table, test_process, NULL);
1038}
1039
1040
1041#endif
1042
1043
b445142a 1044static void push_state(LttvTracefileState *tfs, LttvExecutionMode t,
ffd54a90 1045 guint state_id)
dc877563 1046{
b445142a 1047 LttvExecutionState *es;
348c6ba8 1048
348c6ba8 1049 LttvTraceState *ts = (LttvTraceState*)tfs->parent.t_context;
ae3d0f50 1050 guint cpu = tfs->cpu;
15b3d537 1051
1052#ifdef HASH_TABLE_DEBUG
1053 hash_table_check(ts->processes);
1054#endif
348c6ba8 1055 LttvProcessState *process = ts->running_process[cpu];
dc877563 1056
b445142a 1057 guint depth = process->execution_stack->len;
dc877563 1058
e05fc742 1059 process->execution_stack =
1060 g_array_set_size(process->execution_stack, depth + 1);
1061 /* Keep in sync */
1062 process->state =
1063 &g_array_index(process->execution_stack, LttvExecutionState, depth - 1);
1064
b445142a 1065 es = &g_array_index(process->execution_stack, LttvExecutionState, depth);
1066 es->t = t;
1067 es->n = state_id;
1068 es->entry = es->change = tfs->parent.timestamp;
b49e54b4 1069 es->cum_cpu_time = ltt_time_zero;
b445142a 1070 es->s = process->state->s;
1071 process->state = es;
dc877563 1072}
1073
b49e54b4 1074/* pop state
1075 * return 1 when empty, else 0 */
1076int lttv_state_pop_state_cleanup(LttvProcessState *process,
1077 LttvTracefileState *tfs)
1078{
1079 guint cpu = tfs->cpu;
1080 LttvTraceState *ts = (LttvTraceState*)tfs->parent.t_context;
1081
1082 guint depth = process->execution_stack->len;
1083
1084 if(depth == 1){
1085 return 1;
1086 }
1087
1088 process->execution_stack =
1089 g_array_set_size(process->execution_stack, depth - 1);
1090 process->state = &g_array_index(process->execution_stack, LttvExecutionState,
1091 depth - 2);
1092 process->state->change = tfs->parent.timestamp;
1093
1094 return 0;
1095}
dc877563 1096
b445142a 1097static void pop_state(LttvTracefileState *tfs, LttvExecutionMode t)
dc877563 1098{
ae3d0f50 1099 guint cpu = tfs->cpu;
348c6ba8 1100 LttvTraceState *ts = (LttvTraceState*)tfs->parent.t_context;
1101 LttvProcessState *process = ts->running_process[cpu];
dc877563 1102
f95bc830 1103 guint depth = process->execution_stack->len;
dc877563 1104
3d27549e 1105 if(process->state->t != t){
00e74b69 1106 g_info("Different execution mode type (%lu.%09lu): ignore it\n",
b445142a 1107 tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec);
08b1c66e 1108 g_info("process state has %s when pop_int is %s\n",
8e8e6b64 1109 g_quark_to_string(process->state->t),
1110 g_quark_to_string(t));
7b5f6cf1 1111 g_info("{ %u, %u, %s, %s, %s }\n",
8e8e6b64 1112 process->pid,
1113 process->ppid,
1114 g_quark_to_string(process->name),
7b5f6cf1 1115 g_quark_to_string(process->brand),
8e8e6b64 1116 g_quark_to_string(process->state->s));
3d27549e 1117 return;
1118 }
b445142a 1119
f95bc830 1120 if(depth == 1){
00e74b69 1121 g_info("Trying to pop last state on stack (%lu.%09lu): ignore it\n",
b445142a 1122 tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec);
1123 return;
1124 }
1125
e05fc742 1126 process->execution_stack =
1127 g_array_set_size(process->execution_stack, depth - 1);
b445142a 1128 process->state = &g_array_index(process->execution_stack, LttvExecutionState,
f95bc830 1129 depth - 2);
b445142a 1130 process->state->change = tfs->parent.timestamp;
dc877563 1131}
1132
6806b3c6 1133struct search_result {
1134 const LttTime *time; /* Requested time */
1135 LttTime *best; /* Best result */
1136};
1137
1138static gint search_usertrace(gconstpointer a, gconstpointer b)
1139{
1140 const LttTime *elem_time = (const LttTime*)a;
1141 /* Explicit non const cast */
1142 struct search_result *res = (struct search_result *)b;
1143
1144 if(ltt_time_compare(*elem_time, *(res->time)) < 0) {
1145 /* The usertrace was created before the schedchange */
1146 /* Get larger keys */
1147 return 1;
1148 } else if(ltt_time_compare(*elem_time, *(res->time)) >= 0) {
1149 /* The usertrace was created after the schedchange time */
1150 /* Get smaller keys */
1151 if(res->best) {
1152 if(ltt_time_compare(*elem_time, *res->best) < 0) {
1153 res->best = elem_time;
1154 }
1155 } else {
1156 res->best = elem_time;
1157 }
1158 return -1;
1159 }
14236daa 1160 return 0;
6806b3c6 1161}
1162
1163static LttvTracefileState *ltt_state_usertrace_find(LttvTraceState *tcs,
1164 guint pid, const LttTime *timestamp)
1165{
1166 LttvTracefileState *tfs = NULL;
1167 struct search_result res;
1168 /* Find the usertrace associated with a pid and time interval.
1169 * Search in the usertraces by PID (within a hash) and then, for each
1170 * corresponding element of the array, find the first one with creation
1171 * timestamp the lowest, but higher or equal to "timestamp". */
1172 res.time = timestamp;
1173 res.best = NULL;
1174 GTree *usertrace_tree = g_hash_table_lookup(tcs->usertraces, (gpointer)pid);
1175 if(usertrace_tree) {
1176 g_tree_search(usertrace_tree, search_usertrace, &res);
1177 if(res.best)
1178 tfs = g_tree_lookup(usertrace_tree, res.best);
1179 }
1180
1181 return tfs;
1182}
1183
dc877563 1184
2a2fa4f0 1185LttvProcessState *
348c6ba8 1186lttv_state_create_process(LttvTraceState *tcs, LttvProcessState *parent,
b3fd4c02 1187 guint cpu, guint pid, GQuark name, const LttTime *timestamp)
dc877563 1188{
1189 LttvProcessState *process = g_new(LttvProcessState, 1);
1190
b445142a 1191 LttvExecutionState *es;
dc877563 1192
348c6ba8 1193 LttvTraceContext *tc = (LttvTraceContext*)tcs;
ba576a78 1194
b445142a 1195 char buffer[128];
ffd54a90 1196
dc877563 1197 process->pid = pid;
348c6ba8 1198 process->cpu = cpu;
b3fd4c02 1199 process->name = name;
7b5f6cf1 1200 process->brand = LTTV_STATE_UNBRANDED;
348c6ba8 1201 //process->last_cpu = tfs->cpu_name;
1202 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
e62e7f3a 1203 process->type = LTTV_STATE_USER_THREAD;
6806b3c6 1204 process->usertrace = ltt_state_usertrace_find(tcs, pid, timestamp);
302efbad 1205 process->current_function = 0; //function 0x0 by default.
7bfd7820 1206
cb03932a 1207 g_info("Process %u, core %p", process->pid, process);
2a2fa4f0 1208 g_hash_table_insert(tcs->processes, process, process);
b445142a 1209
1210 if(parent) {
1211 process->ppid = parent->pid;
348c6ba8 1212 process->creation_time = *timestamp;
b445142a 1213 }
2a2fa4f0 1214
1215 /* No parent. This process exists but we are missing all information about
1216 its creation. The birth time is set to zero but we remember the time of
1217 insertion */
1218
b445142a 1219 else {
1220 process->ppid = 0;
2a2fa4f0 1221 process->creation_time = ltt_time_zero;
b445142a 1222 }
1223
348c6ba8 1224 process->insertion_time = *timestamp;
b445142a 1225 sprintf(buffer,"%d-%lu.%lu",pid, process->creation_time.tv_sec,
1226 process->creation_time.tv_nsec);
1227 process->pid_time = g_quark_from_string(buffer);
348c6ba8 1228 process->cpu = cpu;
1229 //process->last_cpu = tfs->cpu_name;
1230 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
e8f2280c 1231 process->execution_stack = g_array_sized_new(FALSE, FALSE,
1232 sizeof(LttvExecutionState), PREALLOCATED_EXECUTION_STACK);
c607371b 1233 process->execution_stack = g_array_set_size(process->execution_stack, 2);
b445142a 1234 es = process->state = &g_array_index(process->execution_stack,
1235 LttvExecutionState, 0);
1236 es->t = LTTV_STATE_USER_MODE;
1237 es->n = LTTV_STATE_SUBMODE_NONE;
348c6ba8 1238 es->entry = *timestamp;
1239 //g_assert(timestamp->tv_sec != 0);
1240 es->change = *timestamp;
b49e54b4 1241 es->cum_cpu_time = ltt_time_zero;
c607371b 1242 es->s = LTTV_STATE_RUN;
1243
1244 es = process->state = &g_array_index(process->execution_stack,
1245 LttvExecutionState, 1);
1246 es->t = LTTV_STATE_SYSCALL;
1247 es->n = LTTV_STATE_SUBMODE_NONE;
1248 es->entry = *timestamp;
1249 //g_assert(timestamp->tv_sec != 0);
1250 es->change = *timestamp;
b49e54b4 1251 es->cum_cpu_time = ltt_time_zero;
b445142a 1252 es->s = LTTV_STATE_WAIT_FORK;
302efbad 1253
1254 /* Allocate an empty function call stack. If it's empty, use 0x0. */
1255 process->user_stack = g_array_sized_new(FALSE, FALSE,
1256 sizeof(guint64), 0);
1257
cbe7c836 1258 return process;
dc877563 1259}
1260
348c6ba8 1261LttvProcessState *lttv_state_find_process(LttvTraceState *ts, guint cpu,
41c7f803 1262 guint pid)
dc877563 1263{
2a2fa4f0 1264 LttvProcessState key;
1265 LttvProcessState *process;
1266
1267 key.pid = pid;
348c6ba8 1268 key.cpu = cpu;
2a2fa4f0 1269 process = g_hash_table_lookup(ts->processes, &key);
dc877563 1270 return process;
1271}
1272
2a2fa4f0 1273LttvProcessState *
348c6ba8 1274lttv_state_find_process_or_create(LttvTraceState *ts, guint cpu, guint pid,
1275 LttTime *timestamp)
2a2fa4f0 1276{
348c6ba8 1277 LttvProcessState *process = lttv_state_find_process(ts, cpu, pid);
7bfd7820 1278 LttvExecutionState *es;
348c6ba8 1279
1280 /* Put ltt_time_zero creation time for unexisting processes */
7bfd7820 1281 if(unlikely(process == NULL)) {
1282 process = lttv_state_create_process(ts,
b3fd4c02 1283 NULL, cpu, pid, LTTV_STATE_UNNAMED, timestamp);
7bfd7820 1284 /* We are not sure is it's a kernel thread or normal thread, put the
1285 * bottom stack state to unknown */
1286 es = &g_array_index(process->execution_stack, LttvExecutionState, 0);
1287 es->t = LTTV_STATE_MODE_UNKNOWN;
1288 }
2a2fa4f0 1289 return process;
1290}
1291
41c7f803 1292/* FIXME : this function should be called when we receive an event telling that
1293 * release_task has been called in the kernel. In happens generally when
1294 * the parent waits for its child terminaison, but may also happen in special
1295 * cases in the child's exit : when the parent ignores its children SIGCCHLD or
1296 * has the flag SA_NOCLDWAIT. It can also happen when the child is part
1297 * of a killed thread ground, but isn't the leader.
41c7f803 1298 */
b445142a 1299static void exit_process(LttvTracefileState *tfs, LttvProcessState *process)
dc877563 1300{
ba576a78 1301 LttvTraceState *ts = LTTV_TRACE_STATE(tfs->parent.t_context);
2a2fa4f0 1302 LttvProcessState key;
ba576a78 1303
2a2fa4f0 1304 key.pid = process->pid;
348c6ba8 1305 key.cpu = process->cpu;
2a2fa4f0 1306 g_hash_table_remove(ts->processes, &key);
b445142a 1307 g_array_free(process->execution_stack, TRUE);
302efbad 1308 g_array_free(process->user_stack, TRUE);
dc877563 1309 g_free(process);
1310}
1311
1312
b445142a 1313static void free_process_state(gpointer key, gpointer value,gpointer user_data)
dc877563 1314{
b445142a 1315 g_array_free(((LttvProcessState *)value)->execution_stack, TRUE);
302efbad 1316 g_array_free(((LttvProcessState *)value)->user_stack, TRUE);
dc877563 1317 g_free(value);
1318}
1319
1320
308711e5 1321static void lttv_state_free_process_table(GHashTable *processes)
dc877563 1322{
1323 g_hash_table_foreach(processes, free_process_state, NULL);
308711e5 1324 g_hash_table_destroy(processes);
dc877563 1325}
1326
1327
b445142a 1328static gboolean syscall_entry(void *hook_data, void *call_data)
dc877563 1329{
ba576a78 1330 LttvTracefileState *s = (LttvTracefileState *)call_data;
eed2ef37 1331 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
d052ffc3 1332 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
eed2ef37 1333 LttField *f = thf->f1;
dc877563 1334
b445142a 1335 LttvExecutionSubmode submode;
1336
7cd289b0 1337 guint nb_syscalls = ((LttvTraceState *)(s->parent.t_context))->nb_syscalls;
1338 guint syscall = ltt_event_get_unsigned(e, f);
1339
1340 if(syscall < nb_syscalls) {
1341 submode = ((LttvTraceState *)(s->parent.t_context))->syscall_names[
1342 syscall];
1343 } else {
1344 /* Fixup an incomplete syscall table */
1345 GString *string = g_string_new("");
1346 g_string_printf(string, "syscall %u", syscall);
1347 submode = g_quark_from_string(string->str);
1348 g_string_free(string, TRUE);
1349 }
b445142a 1350 push_state(s, LTTV_STATE_SYSCALL, submode);
dc877563 1351 return FALSE;
1352}
1353
1354
b445142a 1355static gboolean syscall_exit(void *hook_data, void *call_data)
dc877563 1356{
ba576a78 1357 LttvTracefileState *s = (LttvTracefileState *)call_data;
dc877563 1358
ffd54a90 1359 pop_state(s, LTTV_STATE_SYSCALL);
dc877563 1360 return FALSE;
1361}
1362
1363
b445142a 1364static gboolean trap_entry(void *hook_data, void *call_data)
dc877563 1365{
ba576a78 1366 LttvTracefileState *s = (LttvTracefileState *)call_data;
eed2ef37 1367 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
d052ffc3 1368 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
eed2ef37 1369 LttField *f = thf->f1;
dc877563 1370
b445142a 1371 LttvExecutionSubmode submode;
1372
17ddd1f2 1373 guint64 nb_traps = ((LttvTraceState *)(s->parent.t_context))->nb_traps;
1374 guint64 trap = ltt_event_get_long_unsigned(e, f);
5e96e7e3 1375
1376 if(trap < nb_traps) {
1377 submode = ((LttvTraceState *)(s->parent.t_context))->trap_names[trap];
1378 } else {
1379 /* Fixup an incomplete trap table */
1380 GString *string = g_string_new("");
1381 g_string_printf(string, "trap %u", trap);
1382 submode = g_quark_from_string(string->str);
1383 g_string_free(string, TRUE);
1384 }
1385
b445142a 1386 push_state(s, LTTV_STATE_TRAP, submode);
dc877563 1387 return FALSE;
1388}
1389
1390
b445142a 1391static gboolean trap_exit(void *hook_data, void *call_data)
dc877563 1392{
ba576a78 1393 LttvTracefileState *s = (LttvTracefileState *)call_data;
dc877563 1394
ffd54a90 1395 pop_state(s, LTTV_STATE_TRAP);
dc877563 1396 return FALSE;
1397}
1398
1399
b445142a 1400static gboolean irq_entry(void *hook_data, void *call_data)
dc877563 1401{
ba576a78 1402 LttvTracefileState *s = (LttvTracefileState *)call_data;
eed2ef37 1403 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
9d239bd9 1404 guint8 fac_id = ltt_event_facility_id(e);
1405 guint8 ev_id = ltt_event_eventtype_id(e);
d052ffc3 1406 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
9d239bd9 1407 // g_assert(lttv_trace_hook_get_first((LttvTraceHook *)hook_data)->f1 != NULL);
1408 g_assert(thf->f1 != NULL);
1409 // g_assert(thf == lttv_trace_hook_get_first((LttvTraceHook *)hook_data));
eed2ef37 1410 LttField *f = thf->f1;
dc877563 1411
b445142a 1412 LttvExecutionSubmode submode;
1413
1414 submode = ((LttvTraceState *)(s->parent.t_context))->irq_names[
eed2ef37 1415 ltt_event_get_unsigned(e, f)];
b445142a 1416
dc877563 1417 /* Do something with the info about being in user or system mode when int? */
b445142a 1418 push_state(s, LTTV_STATE_IRQ, submode);
dc877563 1419 return FALSE;
1420}
1421
302efbad 1422static gboolean soft_irq_exit(void *hook_data, void *call_data)
1423{
1424 LttvTracefileState *s = (LttvTracefileState *)call_data;
1425
1426 pop_state(s, LTTV_STATE_SOFT_IRQ);
1427 return FALSE;
1428}
1429
1430
dc877563 1431
b445142a 1432static gboolean irq_exit(void *hook_data, void *call_data)
dc877563 1433{
ba576a78 1434 LttvTracefileState *s = (LttvTracefileState *)call_data;
dc877563 1435
ffd54a90 1436 pop_state(s, LTTV_STATE_IRQ);
dc877563 1437 return FALSE;
1438}
1439
faf074a3 1440static gboolean soft_irq_entry(void *hook_data, void *call_data)
1441{
1442 LttvTracefileState *s = (LttvTracefileState *)call_data;
1443 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
1444 guint8 fac_id = ltt_event_facility_id(e);
1445 guint8 ev_id = ltt_event_eventtype_id(e);
1446 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
1447 // g_assert(lttv_trace_hook_get_first((LttvTraceHook *)hook_data)->f1 != NULL);
1448 g_assert(thf->f1 != NULL);
1449 // g_assert(thf == lttv_trace_hook_get_first((LttvTraceHook *)hook_data));
1450 LttField *f = thf->f1;
1451
1452 LttvExecutionSubmode submode;
1453
1454 submode = ((LttvTraceState *)(s->parent.t_context))->soft_irq_names[
17ddd1f2 1455 ltt_event_get_long_unsigned(e, f)];
faf074a3 1456
1457 /* Do something with the info about being in user or system mode when int? */
1458 push_state(s, LTTV_STATE_SOFT_IRQ, submode);
1459 return FALSE;
1460}
1461
302efbad 1462static void push_function(LttvTracefileState *tfs, guint64 funcptr)
1463{
1464 guint64 *new_func;
1465
1466 LttvTraceState *ts = (LttvTraceState*)tfs->parent.t_context;
1467 guint cpu = tfs->cpu;
1468 LttvProcessState *process = ts->running_process[cpu];
faf074a3 1469
302efbad 1470 guint depth = process->user_stack->len;
1471
1472 process->user_stack =
1473 g_array_set_size(process->user_stack, depth + 1);
1474
1475 new_func = &g_array_index(process->user_stack, guint64, depth);
1476 *new_func = funcptr;
9bff13df 1477 process->current_function = funcptr;
302efbad 1478}
1479
1480static void pop_function(LttvTracefileState *tfs, guint64 funcptr)
1481{
1482 guint cpu = tfs->cpu;
1483 LttvTraceState *ts = (LttvTraceState*)tfs->parent.t_context;
1484 LttvProcessState *process = ts->running_process[cpu];
1485
302efbad 1486 if(process->current_function != funcptr){
1487 g_info("Different functions (%lu.%09lu): ignore it\n",
1488 tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec);
1489 g_info("process state has %llu when pop_function is %llu\n",
1490 process->current_function, funcptr);
7b5f6cf1 1491 g_info("{ %u, %u, %s, %s, %s }\n",
302efbad 1492 process->pid,
1493 process->ppid,
1494 g_quark_to_string(process->name),
7b5f6cf1 1495 g_quark_to_string(process->brand),
302efbad 1496 g_quark_to_string(process->state->s));
1497 return;
1498 }
9bff13df 1499 guint depth = process->user_stack->len;
302efbad 1500
1501 if(depth == 0){
1502 g_info("Trying to pop last function on stack (%lu.%09lu): ignore it\n",
1503 tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec);
1504 return;
1505 }
1506
1507 process->user_stack =
1508 g_array_set_size(process->user_stack, depth - 1);
1509 process->current_function =
1510 g_array_index(process->user_stack, guint64, depth - 2);
1511}
1512
1513
1514static gboolean function_entry(void *hook_data, void *call_data)
faf074a3 1515{
1516 LttvTracefileState *s = (LttvTracefileState *)call_data;
302efbad 1517 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
1518 guint8 fac_id = ltt_event_facility_id(e);
1519 guint8 ev_id = ltt_event_eventtype_id(e);
1520 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
1521 g_assert(thf->f1 != NULL);
1522 LttField *f = thf->f1;
1523 guint64 funcptr = ltt_event_get_long_unsigned(e, f);
faf074a3 1524
302efbad 1525 push_function(s, funcptr);
faf074a3 1526 return FALSE;
1527}
1528
302efbad 1529static gboolean function_exit(void *hook_data, void *call_data)
1530{
1531 LttvTracefileState *s = (LttvTracefileState *)call_data;
1532 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
1533 guint8 fac_id = ltt_event_facility_id(e);
1534 guint8 ev_id = ltt_event_eventtype_id(e);
1535 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
1536 g_assert(thf->f1 != NULL);
1537 LttField *f = thf->f1;
1538 guint64 funcptr = ltt_event_get_long_unsigned(e, f);
1539
1540 LttvExecutionSubmode submode;
1541
1542 pop_function(s, funcptr);
1543 return FALSE;
1544}
dc877563 1545
b445142a 1546static gboolean schedchange(void *hook_data, void *call_data)
dc877563 1547{
ba576a78 1548 LttvTracefileState *s = (LttvTracefileState *)call_data;
ae3d0f50 1549 guint cpu = s->cpu;
348c6ba8 1550 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
1551 LttvProcessState *process = ts->running_process[cpu];
48b002b8 1552 LttvProcessState *old_process = ts->running_process[cpu];
348c6ba8 1553
eed2ef37 1554 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
d052ffc3 1555 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
73394fd3 1556 guint pid_in, pid_out;
1557 gint state_out;
dc877563 1558
eed2ef37 1559 pid_out = ltt_event_get_unsigned(e, thf->f1);
1560 pid_in = ltt_event_get_unsigned(e, thf->f2);
73394fd3 1561 state_out = ltt_event_get_int(e, thf->f3);
348c6ba8 1562
1563 if(likely(process != NULL)) {
b445142a 1564
f95bc830 1565 /* We could not know but it was not the idle process executing.
1566 This should only happen at the beginning, before the first schedule
1567 event, and when the initial information (current process for each CPU)
1568 is missing. It is not obvious how we could, after the fact, compensate
1569 the wrongly attributed statistics. */
1570
240f1fea 1571 //This test only makes sense once the state is known and if there is no
48b002b8 1572 //missing events. We need to silently ignore schedchange coming after a
1573 //process_free, or it causes glitches. (FIXME)
348c6ba8 1574 //if(unlikely(process->pid != pid_out)) {
1575 // g_assert(process->pid == 0);
240f1fea 1576 //}
f95bc830 1577
348c6ba8 1578 if(unlikely(process->state->s == LTTV_STATE_EXIT)) {
1579 process->state->s = LTTV_STATE_ZOMBIE;
791dffa6 1580 process->state->change = s->parent.timestamp;
dbd243b1 1581 } else {
348c6ba8 1582 if(unlikely(state_out == 0)) process->state->s = LTTV_STATE_WAIT_CPU;
1583 else process->state->s = LTTV_STATE_WAIT;
791dffa6 1584 process->state->change = s->parent.timestamp;
1585 }
48b002b8 1586
1587 if(state_out == 32)
791dffa6 1588 exit_process(s, process); /* EXIT_DEAD */
1589 /* see sched.h for states */
dc877563 1590 }
348c6ba8 1591 process = ts->running_process[cpu] =
1592 lttv_state_find_process_or_create(
1593 (LttvTraceState*)s->parent.t_context,
1594 cpu, pid_in,
1595 &s->parent.timestamp);
1596 process->state->s = LTTV_STATE_RUN;
1597 process->cpu = cpu;
ae3d0f50 1598 if(process->usertrace)
1599 process->usertrace->cpu = cpu;
348c6ba8 1600 // process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)s)->tf);
1601 process->state->change = s->parent.timestamp;
dc877563 1602 return FALSE;
1603}
1604
eed2ef37 1605static gboolean process_fork(void *hook_data, void *call_data)
dc877563 1606{
eed2ef37 1607 LttvTracefileState *s = (LttvTracefileState *)call_data;
1608 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
d052ffc3 1609 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
eed2ef37 1610 guint parent_pid;
2cdc690b 1611 guint child_pid;
4ad73431 1612 LttvProcessState *zombie_process;
ae3d0f50 1613 guint cpu = s->cpu;
348c6ba8 1614 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
1615 LttvProcessState *process = ts->running_process[cpu];
26275aa2 1616 LttvProcessState *child_process;
2cdc690b 1617
eed2ef37 1618 /* Parent PID */
b3fd4c02 1619 parent_pid = ltt_event_get_unsigned(e, thf->f1);
eed2ef37 1620
2cdc690b 1621 /* Child PID */
b3fd4c02 1622 child_pid = ltt_event_get_unsigned(e, thf->f2);
2cdc690b 1623
15b3d537 1624 /* Mathieu : it seems like the process might have been scheduled in before the
1625 * fork, and, in a rare case, might be the current process. This might happen
d4942a23 1626 * in a SMP case where we don't have enough precision on the clocks.
1627 *
1628 * Test reenabled after precision fixes on time. (Mathieu) */
791dffa6 1629#if 0
348c6ba8 1630 zombie_process = lttv_state_find_process(ts, ANY_CPU, child_pid);
dc877563 1631
1d1df11d 1632 if(unlikely(zombie_process != NULL)) {
4ad73431 1633 /* Reutilisation of PID. Only now we are sure that the old PID
eed2ef37 1634 * has been released. FIXME : should know when release_task happens instead.
4ad73431 1635 */
15b3d537 1636 guint num_cpus = ltt_trace_get_num_cpu(ts->parent.t);
1637 guint i;
1638 for(i=0; i< num_cpus; i++) {
5ac05980 1639 g_assert(zombie_process != ts->running_process[i]);
15b3d537 1640 }
1641
4ad73431 1642 exit_process(s, zombie_process);
1643 }
791dffa6 1644#endif //0
348c6ba8 1645 g_assert(process->pid != child_pid);
eed2ef37 1646 // FIXME : Add this test in the "known state" section
348c6ba8 1647 // g_assert(process->pid == parent_pid);
26275aa2 1648 child_process = lttv_state_find_process(ts, ANY_CPU, child_pid);
1649 if(child_process == NULL) {
ab893fb1 1650 child_process = lttv_state_create_process(ts, process, cpu,
b3fd4c02 1651 child_pid, LTTV_STATE_UNNAMED, &s->parent.timestamp);
26275aa2 1652 } else {
1653 /* The process has already been created : due to time imprecision between
791dffa6 1654 * multiple CPUs : it has been scheduled in before creation. Note that we
1655 * shouldn't have this kind of imprecision.
26275aa2 1656 *
1657 * Simply put a correct parent.
1658 */
6806b3c6 1659 g_assert(0); /* This is a problematic case : the process has been created
1660 before the fork event */
26275aa2 1661 child_process->ppid = process->pid;
1662 }
ab893fb1 1663 g_assert(child_process->name == LTTV_STATE_UNNAMED);
1664 child_process->name = process->name;
4ad73431 1665
dc877563 1666 return FALSE;
1667}
1668
7bfd7820 1669/* We stamp a newly created process as kernel_thread */
1670static gboolean process_kernel_thread(void *hook_data, void *call_data)
1671{
1672 LttvTracefileState *s = (LttvTracefileState *)call_data;
1673 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
1674 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
1675 guint pid;
ae3d0f50 1676 guint cpu = s->cpu;
7bfd7820 1677 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
1678 LttvProcessState *process;
1679 LttvExecutionState *es;
1680
1681 /* PID */
1682 pid = ltt_event_get_unsigned(e, thf->f1);
1683
1684 process = lttv_state_find_process(ts, ANY_CPU, pid);
1685 es = &g_array_index(process->execution_stack, LttvExecutionState, 0);
1686 es->t = LTTV_STATE_SYSCALL;
e62e7f3a 1687 process->type = LTTV_STATE_KERNEL_THREAD;
7bfd7820 1688
1689 return FALSE;
1690}
dc877563 1691
eed2ef37 1692static gboolean process_exit(void *hook_data, void *call_data)
dc877563 1693{
eed2ef37 1694 LttvTracefileState *s = (LttvTracefileState *)call_data;
1695 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
d052ffc3 1696 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
eed2ef37 1697 LttField *f;
1698 guint pid;
ae3d0f50 1699 guint cpu = s->cpu;
348c6ba8 1700 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
6f54e0f4 1701 LttvProcessState *process; // = ts->running_process[cpu];
eed2ef37 1702
1703 pid = ltt_event_get_unsigned(e, thf->f1);
1704
1705 // FIXME : Add this test in the "known state" section
348c6ba8 1706 // g_assert(process->pid == pid);
eed2ef37 1707
6f54e0f4 1708 process = lttv_state_find_process(ts, ANY_CPU, pid);
348c6ba8 1709 if(likely(process != NULL)) {
1710 process->state->s = LTTV_STATE_EXIT;
2cdc690b 1711 }
1712 return FALSE;
2cdc690b 1713}
1714
eed2ef37 1715static gboolean process_free(void *hook_data, void *call_data)
2da61677 1716{
eed2ef37 1717 LttvTracefileState *s = (LttvTracefileState *)call_data;
348c6ba8 1718 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
eed2ef37 1719 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
d052ffc3 1720 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
2da61677 1721 guint release_pid;
1722 LttvProcessState *process;
1723
1724 /* PID of the process to release */
eed2ef37 1725 release_pid = ltt_event_get_unsigned(e, thf->f1);
15b3d537 1726
1727 g_assert(release_pid != 0);
2da61677 1728
348c6ba8 1729 process = lttv_state_find_process(ts, ANY_CPU, release_pid);
2da61677 1730
1731 if(likely(process != NULL)) {
1732 /* release_task is happening at kernel level : we can now safely release
1733 * the data structure of the process */
5562ddce 1734 //This test is fun, though, as it may happen that
1735 //at time t : CPU 0 : process_free
1736 //at time t+150ns : CPU 1 : schedule out
1737 //Clearly due to time imprecision, we disable it. (Mathieu)
1738 //If this weird case happen, we have no choice but to put the
1739 //Currently running process on the cpu to 0.
791dffa6 1740 //I re-enable it following time precision fixes. (Mathieu)
1741 //Well, in the case where an process is freed by a process on another CPU
1742 //and still scheduled, it happens that this is the schedchange that will
1743 //drop the last reference count. Do not free it here!
0bd2f89c 1744 guint num_cpus = ltt_trace_get_num_cpu(ts->parent.t);
1745 guint i;
1746 for(i=0; i< num_cpus; i++) {
5562ddce 1747 //g_assert(process != ts->running_process[i]);
1748 if(process == ts->running_process[i]) {
791dffa6 1749 //ts->running_process[i] = lttv_state_find_process(ts, i, 0);
1750 break;
5562ddce 1751 }
0bd2f89c 1752 }
6f54e0f4 1753 if(i == num_cpus) /* process is not scheduled */
1754 exit_process(s, process);
2da61677 1755 }
1756
1757 return FALSE;
1758}
1759
f4b88a7d 1760
1761static gboolean process_exec(void *hook_data, void *call_data)
1762{
1763 LttvTracefileState *s = (LttvTracefileState *)call_data;
1764 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
1765 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
1766 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
743e50fd 1767 //gchar *name;
ae3d0f50 1768 guint cpu = s->cpu;
f4b88a7d 1769 LttvProcessState *process = ts->running_process[cpu];
1770
1771 /* PID of the process to release */
743e50fd 1772 guint64 name_len = ltt_event_field_element_number(e, thf->f1);
1773 //name = ltt_event_get_string(e, thf->f1);
f2923fb2 1774 LttField *child = ltt_event_field_element_select(e, thf->f1, 0);
1775 gchar *name_begin =
1776 (gchar*)(ltt_event_data(e)+ltt_event_field_offset(e, child));
743e50fd 1777 gchar *null_term_name = g_new(gchar, name_len+1);
1778 memcpy(null_term_name, name_begin, name_len);
1779 null_term_name[name_len] = '\0';
1780
1781 process->name = g_quark_from_string(null_term_name);
f2923fb2 1782 g_free(null_term_name);
f4b88a7d 1783 return FALSE;
1784}
1785
7b5f6cf1 1786static gboolean thread_brand(void *hook_data, void *call_data)
1787{
1788 LttvTracefileState *s = (LttvTracefileState *)call_data;
1789 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
1790 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
1791 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
1792 gchar *name;
1793 guint cpu = s->cpu;
1794 LttvProcessState *process = ts->running_process[cpu];
1795
1796 name = ltt_event_get_string(e, thf->f1);
1797 process->brand = g_quark_from_string(name);
1798
1799 return FALSE;
1800}
1801
b3fd4c02 1802static gboolean enum_process_state(void *hook_data, void *call_data)
1803{
1804 LttvTracefileState *s = (LttvTracefileState *)call_data;
1805 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
1806 //It's slow : optimise later by doing this before reading trace.
1807 LttEventType *et = ltt_event_eventtype(e);
1808 //
1809 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
1810 guint parent_pid;
1811 guint pid;
1812 gchar * command;
ae3d0f50 1813 guint cpu = s->cpu;
b3fd4c02 1814 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
1815 LttvProcessState *process = ts->running_process[cpu];
1816 LttvProcessState *parent_process;
e62e7f3a 1817 LttField *f4, *f5, *f6, *f7;
1818 GQuark type, mode, submode, status;
1819 LttvExecutionState *es;
f4b88a7d 1820
b3fd4c02 1821 /* PID */
1822 pid = ltt_event_get_unsigned(e, thf->f1);
f4b88a7d 1823
b3fd4c02 1824 /* Parent PID */
1825 parent_pid = ltt_event_get_unsigned(e, thf->f2);
1826
1827 /* Command name */
1828 command = ltt_event_get_string(e, thf->f3);
1829
e62e7f3a 1830 /* type */
1831 f4 = ltt_eventtype_field_by_name(et, LTT_FIELD_TYPE);
1832 type = ltt_enum_string_get(ltt_field_type(f4),
b3fd4c02 1833 ltt_event_get_unsigned(e, f4));
1834
e62e7f3a 1835 /* mode */
1836 f5 = ltt_eventtype_field_by_name(et, LTT_FIELD_MODE);
1837 mode = ltt_enum_string_get(ltt_field_type(f5),
b3fd4c02 1838 ltt_event_get_unsigned(e, f5));
1839
e62e7f3a 1840 /* submode */
1841 f6 = ltt_eventtype_field_by_name(et, LTT_FIELD_SUBMODE);
1842 submode = ltt_enum_string_get(ltt_field_type(f6),
b3fd4c02 1843 ltt_event_get_unsigned(e, f6));
1844
e62e7f3a 1845 /* status */
1846 f7 = ltt_eventtype_field_by_name(et, LTT_FIELD_STATUS);
1847 status = ltt_enum_string_get(ltt_field_type(f7),
1848 ltt_event_get_unsigned(e, f7));
1849
b3fd4c02 1850 /* The process might exist if a process was forked while performing the sate dump. */
1851 process = lttv_state_find_process(ts, ANY_CPU, pid);
1852 if(process == NULL) {
1853 parent_process = lttv_state_find_process(ts, ANY_CPU, parent_pid);
1854 process = lttv_state_create_process(ts, parent_process, cpu,
1855 pid, g_quark_from_string(command),
1856 &s->parent.timestamp);
1857
1858 /* Keep the stack bottom : a running user mode */
ab893fb1 1859 /* Disabled because of inconsistencies in the current statedump states. */
e62e7f3a 1860 if(type == LTTV_STATE_KERNEL_THREAD) {
b3fd4c02 1861 /* Only keep the bottom */
1862 process->execution_stack = g_array_set_size(process->execution_stack, 1);
e62e7f3a 1863 es = process->state = &g_array_index(process->execution_stack,
1864 LttvExecutionState, 0);
1865 es->t = LTTV_STATE_SYSCALL;
1866 es->s = status;
1867 es->n = submode;
b3fd4c02 1868 } else {
1869 /* On top of it : */
b3fd4c02 1870 es = process->state = &g_array_index(process->execution_stack,
1871 LttvExecutionState, 1);
e62e7f3a 1872 es->t = LTTV_STATE_USER_MODE;
b3fd4c02 1873 es->s = status;
1874 es->n = submode;
1875 }
e62e7f3a 1876#if 0
ab893fb1 1877 /* UNKNOWN STATE */
1878 {
ab893fb1 1879 es = process->state = &g_array_index(process->execution_stack,
1880 LttvExecutionState, 1);
1881 es->t = LTTV_STATE_MODE_UNKNOWN;
1882 es->s = LTTV_STATE_UNNAMED;
1883 es->n = LTTV_STATE_SUBMODE_UNKNOWN;
1884 }
e62e7f3a 1885#endif //0
b3fd4c02 1886 } else {
1887 /* The process has already been created :
1888 * Probably was forked while dumping the process state or
1889 * was simply scheduled in prior to get the state dump event.
e62e7f3a 1890 * We know for sure if it is a user space thread.
b3fd4c02 1891 */
1892 process->ppid = parent_pid;
1893 process->name = g_quark_from_string(command);
e62e7f3a 1894 es = &g_array_index(process->execution_stack, LttvExecutionState, 0);
1895 if(type != LTTV_STATE_KERNEL_THREAD)
1896 es->t = LTTV_STATE_USER_MODE;
b3fd4c02 1897 /* Don't mess around with the stack, it will eventually become
1898 * ok after the end of state dump. */
1899 }
1900
1901 return FALSE;
1902}
f4b88a7d 1903
58c88a41 1904gint lttv_state_hook_add_event_hooks(void *hook_data, void *call_data)
1905{
1906 LttvTracesetState *tss = (LttvTracesetState*)(call_data);
1907
1908 lttv_state_add_event_hooks(tss);
1909
1910 return 0;
1911}
dc877563 1912
308711e5 1913void lttv_state_add_event_hooks(LttvTracesetState *self)
dc877563 1914{
ba576a78 1915 LttvTraceset *traceset = self->parent.ts;
dc877563 1916
eed2ef37 1917 guint i, j, k, l, nb_trace, nb_tracefile;
dc877563 1918
ba576a78 1919 LttvTraceState *ts;
dc877563 1920
ba576a78 1921 LttvTracefileState *tfs;
dc877563 1922
dc877563 1923 GArray *hooks;
1924
eed2ef37 1925 LttvTraceHookByFacility *thf;
1926
1927 LttvTraceHook *hook;
dc877563 1928
1929 LttvAttributeValue val;
1930
9d239bd9 1931 gint ret;
302efbad 1932 gint hn;
9d239bd9 1933
ba576a78 1934 nb_trace = lttv_traceset_number(traceset);
dc877563 1935 for(i = 0 ; i < nb_trace ; i++) {
ba576a78 1936 ts = (LttvTraceState *)self->parent.traces[i];
dc877563 1937
1938 /* Find the eventtype id for the following events and register the
1939 associated by id hooks. */
1940
7b5f6cf1 1941 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 18);
1942 hooks = g_array_set_size(hooks, 18); // Max possible number of hooks.
302efbad 1943 hn = 0;
b445142a 1944
9d239bd9 1945 ret = lttv_trace_find_hook(ts->parent.t,
f5d7967f 1946 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_ENTRY,
eed2ef37 1947 LTT_FIELD_SYSCALL_ID, 0, 0,
302efbad 1948 syscall_entry, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
1949 if(ret) hn--;
cbe7c836 1950
9d239bd9 1951 ret = lttv_trace_find_hook(ts->parent.t,
f5d7967f 1952 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_EXIT,
eed2ef37 1953 0, 0, 0,
302efbad 1954 syscall_exit, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
1955 if(ret) hn--;
cbe7c836 1956
9d239bd9 1957 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 1958 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY,
1959 LTT_FIELD_TRAP_ID, 0, 0,
302efbad 1960 trap_entry, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
1961 if(ret) hn--;
cbe7c836 1962
9d239bd9 1963 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 1964 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT,
1965 0, 0, 0,
302efbad 1966 trap_exit, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
1967 if(ret) hn--;
cbe7c836 1968
9d239bd9 1969 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 1970 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
1971 LTT_FIELD_IRQ_ID, 0, 0,
302efbad 1972 irq_entry, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
1973 if(ret) hn--;
cbe7c836 1974
9d239bd9 1975 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 1976 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
1977 0, 0, 0,
302efbad 1978 irq_exit, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
1979 if(ret) hn--;
cbe7c836 1980
faf074a3 1981 ret = lttv_trace_find_hook(ts->parent.t,
1982 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_ENTRY,
1983 LTT_FIELD_SOFT_IRQ_ID, 0, 0,
302efbad 1984 soft_irq_entry, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
1985 if(ret) hn--;
faf074a3 1986
1987 ret = lttv_trace_find_hook(ts->parent.t,
1988 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_EXIT,
1989 0, 0, 0,
302efbad 1990 soft_irq_exit, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
1991 if(ret) hn--;
faf074a3 1992
9d239bd9 1993 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 1994 LTT_FACILITY_PROCESS, LTT_EVENT_SCHEDCHANGE,
1995 LTT_FIELD_OUT, LTT_FIELD_IN, LTT_FIELD_OUT_STATE,
302efbad 1996 schedchange, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
1997 if(ret) hn--;
cbe7c836 1998
9d239bd9 1999 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 2000 LTT_FACILITY_PROCESS, LTT_EVENT_FORK,
2001 LTT_FIELD_PARENT_PID, LTT_FIELD_CHILD_PID, 0,
302efbad 2002 process_fork, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
2003 if(ret) hn--;
eed2ef37 2004
7bfd7820 2005 ret = lttv_trace_find_hook(ts->parent.t,
2006 LTT_FACILITY_PROCESS, LTT_EVENT_KERNEL_THREAD,
2007 LTT_FIELD_PID, 0, 0,
302efbad 2008 process_kernel_thread, NULL, &g_array_index(hooks, LttvTraceHook,
2009 hn++));
2010 if(ret) hn--;
7bfd7820 2011
9d239bd9 2012 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 2013 LTT_FACILITY_PROCESS, LTT_EVENT_EXIT,
2014 LTT_FIELD_PID, 0, 0,
302efbad 2015 process_exit, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
2016 if(ret) hn--;
eed2ef37 2017
9d239bd9 2018 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 2019 LTT_FACILITY_PROCESS, LTT_EVENT_FREE,
2020 LTT_FIELD_PID, 0, 0,
302efbad 2021 process_free, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
2022 if(ret) hn--;
2cdc690b 2023
f4b88a7d 2024 ret = lttv_trace_find_hook(ts->parent.t,
2025 LTT_FACILITY_FS, LTT_EVENT_EXEC,
2026 LTT_FIELD_FILENAME, 0, 0,
302efbad 2027 process_exec, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
2028 if(ret) hn--;
f4b88a7d 2029
7b5f6cf1 2030 ret = lttv_trace_find_hook(ts->parent.t,
2031 LTT_FACILITY_USER_GENERIC, LTT_EVENT_THREAD_BRAND,
2032 LTT_FIELD_NAME, 0, 0,
2033 thread_brand, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
2034 if(ret) hn--;
2035
b3fd4c02 2036 /* statedump-related hooks */
2037 ret = lttv_trace_find_hook(ts->parent.t,
2038 LTT_FACILITY_STATEDUMP, LTT_EVENT_ENUM_PROCESS_STATE,
2039 LTT_FIELD_PID, LTT_FIELD_PARENT_PID, LTT_FIELD_NAME,
302efbad 2040 enum_process_state, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
2041 if(ret) hn--;
f4b88a7d 2042
302efbad 2043 ret = lttv_trace_find_hook(ts->parent.t,
2044 LTT_FACILITY_USER_GENERIC, LTT_EVENT_FUNCTION_ENTRY,
2045 LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE, 0,
2046 function_entry, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
2047 if(ret) hn--;
2048
2049 ret = lttv_trace_find_hook(ts->parent.t,
2050 LTT_FACILITY_USER_GENERIC, LTT_EVENT_FUNCTION_EXIT,
2051 LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE, 0,
2052 function_exit, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
2053 if(ret) hn--;
2054
2055 hooks = g_array_set_size(hooks, hn);
2056
a5ba1787 2057 /* Add these hooks to each event_by_id hooks list */
dc877563 2058
eed2ef37 2059 nb_tracefile = ts->parent.tracefiles->len;
dbb7bb09 2060
dc877563 2061 for(j = 0 ; j < nb_tracefile ; j++) {
eed2ef37 2062 tfs =
9d239bd9 2063 LTTV_TRACEFILE_STATE(g_array_index(ts->parent.tracefiles,
2064 LttvTracefileContext*, j));
dc877563 2065
2066 for(k = 0 ; k < hooks->len ; k++) {
eed2ef37 2067 hook = &g_array_index(hooks, LttvTraceHook, k);
2068 for(l=0;l<hook->fac_list->len;l++) {
2069 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
2070 lttv_hooks_add(
2071 lttv_hooks_by_id_find(tfs->parent.event_by_id, thf->id),
2072 thf->h,
d052ffc3 2073 thf,
eed2ef37 2074 LTTV_PRIO_STATE);
2075 }
ffd54a90 2076 }
dc877563 2077 }
f0b795e0 2078 lttv_attribute_find(ts->parent.a, LTTV_STATE_HOOKS, LTTV_POINTER, &val);
ba576a78 2079 *(val.v_pointer) = hooks;
dc877563 2080 }
2081}
2082
58c88a41 2083gint lttv_state_hook_remove_event_hooks(void *hook_data, void *call_data)
2084{
2085 LttvTracesetState *tss = (LttvTracesetState*)(call_data);
2086
2087 lttv_state_remove_event_hooks(tss);
2088
2089 return 0;
2090}
dc877563 2091
308711e5 2092void lttv_state_remove_event_hooks(LttvTracesetState *self)
dc877563 2093{
ba576a78 2094 LttvTraceset *traceset = self->parent.ts;
dc877563 2095
eed2ef37 2096 guint i, j, k, l, nb_trace, nb_tracefile;
dc877563 2097
ba576a78 2098 LttvTraceState *ts;
dc877563 2099
ba576a78 2100 LttvTracefileState *tfs;
dc877563 2101
dc877563 2102 GArray *hooks;
2103
eed2ef37 2104 LttvTraceHook *hook;
2105
2106 LttvTraceHookByFacility *thf;
dc877563 2107
2108 LttvAttributeValue val;
2109
ba576a78 2110 nb_trace = lttv_traceset_number(traceset);
dc877563 2111 for(i = 0 ; i < nb_trace ; i++) {
021eeb41 2112 ts = LTTV_TRACE_STATE(self->parent.traces[i]);
f0b795e0 2113 lttv_attribute_find(ts->parent.a, LTTV_STATE_HOOKS, LTTV_POINTER, &val);
ba576a78 2114 hooks = *(val.v_pointer);
dc877563 2115
a5ba1787 2116 /* Remove these hooks from each event_by_id hooks list */
dc877563 2117
eed2ef37 2118 nb_tracefile = ts->parent.tracefiles->len;
dbb7bb09 2119
dc877563 2120 for(j = 0 ; j < nb_tracefile ; j++) {
eed2ef37 2121 tfs =
cb03932a 2122 LTTV_TRACEFILE_STATE(g_array_index(ts->parent.tracefiles,
2123 LttvTracefileContext*, j));
dc877563 2124
2125 for(k = 0 ; k < hooks->len ; k++) {
eed2ef37 2126 hook = &g_array_index(hooks, LttvTraceHook, k);
2127 for(l=0;l<hook->fac_list->len;l++) {
2128 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
2129
2130 lttv_hooks_remove_data(
2131 lttv_hooks_by_id_find(tfs->parent.event_by_id, thf->id),
2132 thf->h,
d052ffc3 2133 thf);
eed2ef37 2134 }
ffd54a90 2135 }
dc877563 2136 }
1986f254 2137 for(k = 0 ; k < hooks->len ; k++)
2138 lttv_trace_hook_destroy(&g_array_index(hooks, LttvTraceHook, k));
dc877563 2139 g_array_free(hooks, TRUE);
2140 }
2141}
2142
eed2ef37 2143static gboolean state_save_event_hook(void *hook_data, void *call_data)
2144{
2145 guint *event_count = (guint*)hook_data;
2146
2147 /* Only save at LTTV_STATE_SAVE_INTERVAL */
2148 if(likely((*event_count)++ < LTTV_STATE_SAVE_INTERVAL))
2149 return FALSE;
2150 else
18c87975 2151 *event_count = 0;
eed2ef37 2152
2153 LttvTracefileState *self = (LttvTracefileState *)call_data;
2154
2155 LttvTracefileState *tfcs;
2156
2157 LttvTraceState *tcs = (LttvTraceState *)(self->parent.t_context);
2158
2159 LttEventPosition *ep;
2160
2161 guint i;
2162
2163 LttTracefile *tf;
2164
2165 LttvAttribute *saved_states_tree, *saved_state_tree;
2166
2167 LttvAttributeValue value;
2168
2169 saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a,
2170 LTTV_STATE_SAVED_STATES);
2171 saved_state_tree = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
2172 value = lttv_attribute_add(saved_states_tree,
2173 lttv_attribute_get_number(saved_states_tree), LTTV_GOBJECT);
2174 *(value.v_gobject) = (GObject *)saved_state_tree;
2175 value = lttv_attribute_add(saved_state_tree, LTTV_STATE_TIME, LTTV_TIME);
2176 *(value.v_time) = self->parent.timestamp;
2177 lttv_state_save(tcs, saved_state_tree);
2178 g_debug("Saving state at time %lu.%lu", self->parent.timestamp.tv_sec,
2179 self->parent.timestamp.tv_nsec);
2180
2181 *(tcs->max_time_state_recomputed_in_seek) = self->parent.timestamp;
2182
2183 return FALSE;
2184}
2185
14aecf75 2186static gboolean state_save_after_trace_hook(void *hook_data, void *call_data)
2187{
2188 LttvTraceState *tcs = (LttvTraceState *)(call_data);
2189
2190 *(tcs->max_time_state_recomputed_in_seek) = tcs->parent.time_span.end_time;
2191
2192 return FALSE;
2193}
2194
ae3d0f50 2195guint lttv_state_current_cpu(LttvTracefileState *tfs)
2196{
2197 return tfs->cpu;
2198}
2199
2200
2201
eed2ef37 2202#if 0
08b1c66e 2203static gboolean block_start(void *hook_data, void *call_data)
308711e5 2204{
dbb7bb09 2205 LttvTracefileState *self = (LttvTracefileState *)call_data;
308711e5 2206
dbb7bb09 2207 LttvTracefileState *tfcs;
308711e5 2208
dbb7bb09 2209 LttvTraceState *tcs = (LttvTraceState *)(self->parent.t_context);
2210
2211 LttEventPosition *ep;
308711e5 2212
dbb7bb09 2213 guint i, nb_block, nb_event, nb_tracefile;
308711e5 2214
2215 LttTracefile *tf;
2216
2217 LttvAttribute *saved_states_tree, *saved_state_tree;
2218
2219 LttvAttributeValue value;
2220
dbb7bb09 2221 ep = ltt_event_position_new();
eed2ef37 2222
2223 nb_tracefile = tcs->parent.tracefiles->len;
dbb7bb09 2224
2225 /* Count the number of events added since the last block end in any
2226 tracefile. */
2227
2228 for(i = 0 ; i < nb_tracefile ; i++) {
eed2ef37 2229 tfcs =
2230 LTTV_TRACEFILE_STATE(&g_array_index(tcs->parent.tracefiles,
2231 LttvTracefileContext, i));
dbb7bb09 2232 ltt_event_position(tfcs->parent.e, ep);
2233 ltt_event_position_get(ep, &nb_block, &nb_event, &tf);
2234 tcs->nb_event += nb_event - tfcs->saved_position;
2235 tfcs->saved_position = nb_event;
2236 }
2237 g_free(ep);
308711e5 2238
308711e5 2239 if(tcs->nb_event >= tcs->save_interval) {
2240 saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a,
2241 LTTV_STATE_SAVED_STATES);
2242 saved_state_tree = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
2243 value = lttv_attribute_add(saved_states_tree,
2244 lttv_attribute_get_number(saved_states_tree), LTTV_GOBJECT);
2245 *(value.v_gobject) = (GObject *)saved_state_tree;
2246 value = lttv_attribute_add(saved_state_tree, LTTV_STATE_TIME, LTTV_TIME);
dbb7bb09 2247 *(value.v_time) = self->parent.timestamp;
308711e5 2248 lttv_state_save(tcs, saved_state_tree);
2249 tcs->nb_event = 0;
08b1c66e 2250 g_debug("Saving state at time %lu.%lu", self->parent.timestamp.tv_sec,
2251 self->parent.timestamp.tv_nsec);
308711e5 2252 }
dbb7bb09 2253 *(tcs->max_time_state_recomputed_in_seek) = self->parent.timestamp;
308711e5 2254 return FALSE;
2255}
eed2ef37 2256#endif //0
308711e5 2257
eed2ef37 2258#if 0
08b1c66e 2259static gboolean block_end(void *hook_data, void *call_data)
2260{
2261 LttvTracefileState *self = (LttvTracefileState *)call_data;
2262
2263 LttvTraceState *tcs = (LttvTraceState *)(self->parent.t_context);
2264
2265 LttTracefile *tf;
2266
2267 LttEventPosition *ep;
2268
2269 guint nb_block, nb_event;
2270
2271 ep = ltt_event_position_new();
2272 ltt_event_position(self->parent.e, ep);
2273 ltt_event_position_get(ep, &nb_block, &nb_event, &tf);
2274 tcs->nb_event += nb_event - self->saved_position + 1;
2275 self->saved_position = 0;
2276 *(tcs->max_time_state_recomputed_in_seek) = self->parent.timestamp;
2277 g_free(ep);
00e74b69 2278
2279 return FALSE;
08b1c66e 2280}
eed2ef37 2281#endif //0
2282#if 0
308711e5 2283void lttv_state_save_add_event_hooks(LttvTracesetState *self)
2284{
2285 LttvTraceset *traceset = self->parent.ts;
2286
00e74b69 2287 guint i, j, nb_trace, nb_tracefile;
308711e5 2288
2289 LttvTraceState *ts;
2290
2291 LttvTracefileState *tfs;
2292
08b1c66e 2293 LttvTraceHook hook_start, hook_end;
308711e5 2294
2295 nb_trace = lttv_traceset_number(traceset);
2296 for(i = 0 ; i < nb_trace ; i++) {
2297 ts = (LttvTraceState *)self->parent.traces[i];
eed2ef37 2298
08b1c66e 2299 lttv_trace_find_hook(ts->parent.t, "core","block_start",NULL,
2300 NULL, NULL, block_start, &hook_start);
308711e5 2301 lttv_trace_find_hook(ts->parent.t, "core","block_end",NULL,
08b1c66e 2302 NULL, NULL, block_end, &hook_end);
308711e5 2303
eed2ef37 2304 nb_tracefile = ts->parent.tracefiles->len;
308711e5 2305
dbb7bb09 2306 for(j = 0 ; j < nb_tracefile ; j++) {
eed2ef37 2307 tfs =
2308 LTTV_TRACEFILE_STATE(&g_array_index(ts->parent.tracefiles,
2309 LttvTracefileContext, j));
a5ba1787 2310 lttv_hooks_add(lttv_hooks_by_id_find(tfs->parent.event_by_id,
eed2ef37 2311 hook_start.id), hook_start.h, NULL, LTTV_PRIO_STATE);
a5ba1787 2312 lttv_hooks_add(lttv_hooks_by_id_find(tfs->parent.event_by_id,
eed2ef37 2313 hook_end.id), hook_end.h, NULL, LTTV_PRIO_STATE);
2314 }
2315 }
2316}
2317#endif //0
2318
2319void lttv_state_save_add_event_hooks(LttvTracesetState *self)
2320{
2321 LttvTraceset *traceset = self->parent.ts;
2322
2323 guint i, j, nb_trace, nb_tracefile;
2324
2325 LttvTraceState *ts;
2326
2327 LttvTracefileState *tfs;
2328
2329
2330 nb_trace = lttv_traceset_number(traceset);
2331 for(i = 0 ; i < nb_trace ; i++) {
2332
2333 ts = (LttvTraceState *)self->parent.traces[i];
2334 nb_tracefile = ts->parent.tracefiles->len;
2335
3054461a 2336 guint *event_count = g_new(guint, 1);
2337 *event_count = 0;
2338
eed2ef37 2339 for(j = 0 ; j < nb_tracefile ; j++) {
2340 tfs =
cb03932a 2341 LTTV_TRACEFILE_STATE(g_array_index(ts->parent.tracefiles,
2342 LttvTracefileContext*, j));
eed2ef37 2343 lttv_hooks_add(tfs->parent.event,
2344 state_save_event_hook,
2345 event_count,
2346 LTTV_PRIO_STATE);
2347
308711e5 2348 }
2349 }
14aecf75 2350
2351 lttv_process_traceset_begin(&self->parent,
2352 NULL, NULL, NULL, NULL, NULL);
2353
308711e5 2354}
2355
b56b5fec 2356gint lttv_state_save_hook_add_event_hooks(void *hook_data, void *call_data)
2357{
2358 LttvTracesetState *tss = (LttvTracesetState*)(call_data);
2359
2360 lttv_state_save_add_event_hooks(tss);
2361
2362 return 0;
2363}
2364
308711e5 2365
eed2ef37 2366#if 0
308711e5 2367void lttv_state_save_remove_event_hooks(LttvTracesetState *self)
2368{
2369 LttvTraceset *traceset = self->parent.ts;
2370
00e74b69 2371 guint i, j, nb_trace, nb_tracefile;
308711e5 2372
2373 LttvTraceState *ts;
2374
2375 LttvTracefileState *tfs;
2376
08b1c66e 2377 LttvTraceHook hook_start, hook_end;
308711e5 2378
2379 nb_trace = lttv_traceset_number(traceset);
2380 for(i = 0 ; i < nb_trace ; i++) {
2381 ts = LTTV_TRACE_STATE(self->parent.traces[i]);
eed2ef37 2382
08b1c66e 2383 lttv_trace_find_hook(ts->parent.t, "core","block_start",NULL,
2384 NULL, NULL, block_start, &hook_start);
2385
308711e5 2386 lttv_trace_find_hook(ts->parent.t, "core","block_end",NULL,
08b1c66e 2387 NULL, NULL, block_end, &hook_end);
308711e5 2388
eed2ef37 2389 nb_tracefile = ts->parent.tracefiles->len;
308711e5 2390
dbb7bb09 2391 for(j = 0 ; j < nb_tracefile ; j++) {
eed2ef37 2392 tfs =
2393 LTTV_TRACEFILE_STATE(&g_array_index(ts->parent.tracefiles,
2394 LttvTracefileContext, j));
308711e5 2395 lttv_hooks_remove_data(lttv_hooks_by_id_find(
a5ba1787 2396 tfs->parent.event_by_id, hook_start.id), hook_start.h, NULL);
08b1c66e 2397 lttv_hooks_remove_data(lttv_hooks_by_id_find(
a5ba1787 2398 tfs->parent.event_by_id, hook_end.id), hook_end.h, NULL);
308711e5 2399 }
2400 }
2401}
eed2ef37 2402#endif //0
2403
2404void lttv_state_save_remove_event_hooks(LttvTracesetState *self)
2405{
2406 LttvTraceset *traceset = self->parent.ts;
2407
2408 guint i, j, nb_trace, nb_tracefile;
2409
2410 LttvTraceState *ts;
2411
2412 LttvTracefileState *tfs;
2413
14aecf75 2414 LttvHooks *after_trace = lttv_hooks_new();
2415
2416 lttv_hooks_add(after_trace,
2417 state_save_after_trace_hook,
2418 NULL,
2419 LTTV_PRIO_STATE);
2420
2421
2422 lttv_process_traceset_end(&self->parent,
2423 NULL, after_trace, NULL, NULL, NULL);
eed2ef37 2424
14aecf75 2425 lttv_hooks_destroy(after_trace);
2426
eed2ef37 2427 nb_trace = lttv_traceset_number(traceset);
2428 for(i = 0 ; i < nb_trace ; i++) {
2429
2430 ts = (LttvTraceState *)self->parent.traces[i];
2431 nb_tracefile = ts->parent.tracefiles->len;
2432
22b165e9 2433 guint *event_count = NULL;
eed2ef37 2434
2435 for(j = 0 ; j < nb_tracefile ; j++) {
2436 tfs =
cb03932a 2437 LTTV_TRACEFILE_STATE(g_array_index(ts->parent.tracefiles,
2438 LttvTracefileContext*, j));
eed2ef37 2439 event_count = lttv_hooks_remove(tfs->parent.event,
2440 state_save_event_hook);
eed2ef37 2441 }
22b165e9 2442 if(event_count) g_free(event_count);
eed2ef37 2443 }
2444}
308711e5 2445
b56b5fec 2446gint lttv_state_save_hook_remove_event_hooks(void *hook_data, void *call_data)
2447{
2448 LttvTracesetState *tss = (LttvTracesetState*)(call_data);
2449
2450 lttv_state_save_remove_event_hooks(tss);
2451
2452 return 0;
2453}
308711e5 2454
dd025f91 2455void lttv_state_traceset_seek_time_closest(LttvTracesetState *self, LttTime t)
308711e5 2456{
2457 LttvTraceset *traceset = self->parent.ts;
2458
00e74b69 2459 guint i, nb_trace;
308711e5 2460
2461 int min_pos, mid_pos, max_pos;
2462
728d0c3e 2463 guint call_rest = 0;
2464
308711e5 2465 LttvTraceState *tcs;
2466
2467 LttvAttributeValue value;
2468
2469 LttvAttributeType type;
2470
2471 LttvAttributeName name;
2472
c0cb4d12 2473 gboolean is_named;
2474
308711e5 2475 LttvAttribute *saved_states_tree, *saved_state_tree, *closest_tree;
2476
d448fce2 2477 //g_tree_destroy(self->parent.pqueue);
2478 //self->parent.pqueue = g_tree_new(compare_tracefile);
348c6ba8 2479
728d0c3e 2480 g_info("Entering seek_time_closest for time %lu.%lu", t.tv_sec, t.tv_nsec);
2481
308711e5 2482 nb_trace = lttv_traceset_number(traceset);
2483 for(i = 0 ; i < nb_trace ; i++) {
2484 tcs = (LttvTraceState *)self->parent.traces[i];
2485
2a2fa4f0 2486 if(ltt_time_compare(t, *(tcs->max_time_state_recomputed_in_seek)) < 0) {
2487 saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a,
2488 LTTV_STATE_SAVED_STATES);
2489 min_pos = -1;
2490
2491 if(saved_states_tree) {
dd025f91 2492 max_pos = lttv_attribute_get_number(saved_states_tree) - 1;
2493 mid_pos = max_pos / 2;
2494 while(min_pos < max_pos) {
c0cb4d12 2495 type = lttv_attribute_get(saved_states_tree, mid_pos, &name, &value,
2496 &is_named);
dd025f91 2497 g_assert(type == LTTV_GOBJECT);
2498 saved_state_tree = *((LttvAttribute **)(value.v_gobject));
2499 type = lttv_attribute_get_by_name(saved_state_tree, LTTV_STATE_TIME,
2500 &value);
2501 g_assert(type == LTTV_TIME);
2502 if(ltt_time_compare(*(value.v_time), t) < 0) {
2503 min_pos = mid_pos;
2504 closest_tree = saved_state_tree;
2505 }
2506 else max_pos = mid_pos - 1;
2507
2508 mid_pos = (min_pos + max_pos + 1) / 2;
2509 }
2a2fa4f0 2510 }
dd025f91 2511
2a2fa4f0 2512 /* restore the closest earlier saved state */
f95bc830 2513 if(min_pos != -1) {
2514 lttv_state_restore(tcs, closest_tree);
728d0c3e 2515 call_rest = 1;
f95bc830 2516 }
dd025f91 2517
2a2fa4f0 2518 /* There is no saved state, yet we want to have it. Restart at T0 */
dd025f91 2519 else {
2520 restore_init_state(tcs);
2521 lttv_process_trace_seek_time(&(tcs->parent), ltt_time_zero);
308711e5 2522 }
9444deae 2523 }
dd025f91 2524 /* We want to seek quickly without restoring/updating the state */
2525 else {
308711e5 2526 restore_init_state(tcs);
dd025f91 2527 lttv_process_trace_seek_time(&(tcs->parent), t);
308711e5 2528 }
308711e5 2529 }
728d0c3e 2530 if(!call_rest) g_info("NOT Calling restore");
308711e5 2531}
2532
2533
2534static void
2535traceset_state_instance_init (GTypeInstance *instance, gpointer g_class)
2536{
2537}
2538
2539
2540static void
2541traceset_state_finalize (LttvTracesetState *self)
2542{
2543 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))->
2544 finalize(G_OBJECT(self));
2545}
2546
2547
2548static void
2549traceset_state_class_init (LttvTracesetContextClass *klass)
2550{
2551 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
2552
2553 gobject_class->finalize = (void (*)(GObject *self)) traceset_state_finalize;
2554 klass->init = (void (*)(LttvTracesetContext *self, LttvTraceset *ts))init;
2555 klass->fini = (void (*)(LttvTracesetContext *self))fini;
2556 klass->new_traceset_context = new_traceset_context;
2557 klass->new_trace_context = new_trace_context;
2558 klass->new_tracefile_context = new_tracefile_context;
2559}
2560
2561
2562GType
2563lttv_traceset_state_get_type(void)
2564{
2565 static GType type = 0;
2566 if (type == 0) {
2567 static const GTypeInfo info = {
2568 sizeof (LttvTracesetStateClass),
2569 NULL, /* base_init */
2570 NULL, /* base_finalize */
2571 (GClassInitFunc) traceset_state_class_init, /* class_init */
2572 NULL, /* class_finalize */
2573 NULL, /* class_data */
dbb7bb09 2574 sizeof (LttvTracesetState),
308711e5 2575 0, /* n_preallocs */
00e74b69 2576 (GInstanceInitFunc) traceset_state_instance_init, /* instance_init */
2577 NULL /* value handling */
308711e5 2578 };
2579
2580 type = g_type_register_static (LTTV_TRACESET_CONTEXT_TYPE, "LttvTracesetStateType",
2581 &info, 0);
2582 }
2583 return type;
2584}
2585
2586
2587static void
2588trace_state_instance_init (GTypeInstance *instance, gpointer g_class)
2589{
2590}
2591
2592
2593static void
2594trace_state_finalize (LttvTraceState *self)
2595{
2596 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_CONTEXT_TYPE))->
2597 finalize(G_OBJECT(self));
2598}
2599
2600
2601static void
2602trace_state_class_init (LttvTraceStateClass *klass)
2603{
2604 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
2605
2606 gobject_class->finalize = (void (*)(GObject *self)) trace_state_finalize;
2607 klass->state_save = state_save;
2608 klass->state_restore = state_restore;
2609 klass->state_saved_free = state_saved_free;
2610}
2611
2612
2613GType
2614lttv_trace_state_get_type(void)
2615{
2616 static GType type = 0;
2617 if (type == 0) {
2618 static const GTypeInfo info = {
2619 sizeof (LttvTraceStateClass),
2620 NULL, /* base_init */
2621 NULL, /* base_finalize */
2622 (GClassInitFunc) trace_state_class_init, /* class_init */
2623 NULL, /* class_finalize */
2624 NULL, /* class_data */
2625 sizeof (LttvTraceState),
2626 0, /* n_preallocs */
00e74b69 2627 (GInstanceInitFunc) trace_state_instance_init, /* instance_init */
2628 NULL /* value handling */
308711e5 2629 };
2630
2631 type = g_type_register_static (LTTV_TRACE_CONTEXT_TYPE,
2632 "LttvTraceStateType", &info, 0);
2633 }
2634 return type;
2635}
2636
2637
2638static void
2639tracefile_state_instance_init (GTypeInstance *instance, gpointer g_class)
2640{
2641}
2642
2643
2644static void
2645tracefile_state_finalize (LttvTracefileState *self)
2646{
2647 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_CONTEXT_TYPE))->
2648 finalize(G_OBJECT(self));
2649}
2650
2651
2652static void
2653tracefile_state_class_init (LttvTracefileStateClass *klass)
2654{
2655 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
2656
2657 gobject_class->finalize = (void (*)(GObject *self)) tracefile_state_finalize;
2658}
2659
2660
2661GType
2662lttv_tracefile_state_get_type(void)
2663{
2664 static GType type = 0;
2665 if (type == 0) {
2666 static const GTypeInfo info = {
2667 sizeof (LttvTracefileStateClass),
2668 NULL, /* base_init */
2669 NULL, /* base_finalize */
2670 (GClassInitFunc) tracefile_state_class_init, /* class_init */
2671 NULL, /* class_finalize */
2672 NULL, /* class_data */
2673 sizeof (LttvTracefileState),
2674 0, /* n_preallocs */
00e74b69 2675 (GInstanceInitFunc) tracefile_state_instance_init, /* instance_init */
2676 NULL /* value handling */
308711e5 2677 };
2678
2679 type = g_type_register_static (LTTV_TRACEFILE_CONTEXT_TYPE,
2680 "LttvTracefileStateType", &info, 0);
2681 }
2682 return type;
2683}
2684
2685
08b1c66e 2686static void module_init()
ffd54a90 2687{
83e160f2 2688 LTTV_STATE_UNNAMED = g_quark_from_string("UNNAMED");
7b5f6cf1 2689 LTTV_STATE_UNBRANDED = g_quark_from_string("UNBRANDED");
b3fd4c02 2690 LTTV_STATE_MODE_UNKNOWN = g_quark_from_string("MODE_UNKNOWN");
2691 LTTV_STATE_USER_MODE = g_quark_from_string("USER_MODE");
2692 LTTV_STATE_SYSCALL = g_quark_from_string("SYSCALL");
2693 LTTV_STATE_TRAP = g_quark_from_string("TRAP");
2694 LTTV_STATE_IRQ = g_quark_from_string("IRQ");
2695 LTTV_STATE_SOFT_IRQ = g_quark_from_string("SOFTIRQ");
2696 LTTV_STATE_SUBMODE_UNKNOWN = g_quark_from_string("UNKNOWN");
2697 LTTV_STATE_SUBMODE_NONE = g_quark_from_string("NONE");
2698 LTTV_STATE_WAIT_FORK = g_quark_from_string("WAIT_FORK");
2699 LTTV_STATE_WAIT_CPU = g_quark_from_string("WAIT_CPU");
2700 LTTV_STATE_EXIT = g_quark_from_string("EXIT");
2701 LTTV_STATE_ZOMBIE = g_quark_from_string("ZOMBIE");
2702 LTTV_STATE_WAIT = g_quark_from_string("WAIT");
2703 LTTV_STATE_RUN = g_quark_from_string("RUN");
2704 LTTV_STATE_DEAD = g_quark_from_string("DEAD");
e62e7f3a 2705 LTTV_STATE_USER_THREAD = g_quark_from_string("USER_THREAD");
2706 LTTV_STATE_KERNEL_THREAD = g_quark_from_string("KERNEL_THREAD");
308711e5 2707 LTTV_STATE_TRACEFILES = g_quark_from_string("tracefiles");
2708 LTTV_STATE_PROCESSES = g_quark_from_string("processes");
2709 LTTV_STATE_PROCESS = g_quark_from_string("process");
348c6ba8 2710 LTTV_STATE_RUNNING_PROCESS = g_quark_from_string("running_process");
308711e5 2711 LTTV_STATE_EVENT = g_quark_from_string("event");
2712 LTTV_STATE_SAVED_STATES = g_quark_from_string("saved states");
dbb7bb09 2713 LTTV_STATE_SAVED_STATES_TIME = g_quark_from_string("saved states time");
308711e5 2714 LTTV_STATE_TIME = g_quark_from_string("time");
ffd54a90 2715 LTTV_STATE_HOOKS = g_quark_from_string("saved state hooks");
f95bc830 2716 LTTV_STATE_NAME_TABLES = g_quark_from_string("name tables");
2717 LTTV_STATE_TRACE_STATE_USE_COUNT =
2718 g_quark_from_string("trace_state_use_count");
eed2ef37 2719
2720
2721 LTT_FACILITY_KERNEL = g_quark_from_string("kernel");
f5d7967f 2722 LTT_FACILITY_KERNEL_ARCH = g_quark_from_string("kernel_arch");
eed2ef37 2723 LTT_FACILITY_PROCESS = g_quark_from_string("process");
f4b88a7d 2724 LTT_FACILITY_FS = g_quark_from_string("fs");
b3fd4c02 2725 LTT_FACILITY_STATEDUMP = g_quark_from_string("statedump");
302efbad 2726 LTT_FACILITY_USER_GENERIC = g_quark_from_string("user_generic");
eed2ef37 2727
2728
2729 LTT_EVENT_SYSCALL_ENTRY = g_quark_from_string("syscall_entry");
2730 LTT_EVENT_SYSCALL_EXIT = g_quark_from_string("syscall_exit");
2731 LTT_EVENT_TRAP_ENTRY = g_quark_from_string("trap_entry");
2732 LTT_EVENT_TRAP_EXIT = g_quark_from_string("trap_exit");
2733 LTT_EVENT_IRQ_ENTRY = g_quark_from_string("irq_entry");
2734 LTT_EVENT_IRQ_EXIT = g_quark_from_string("irq_exit");
faf074a3 2735 LTT_EVENT_SOFT_IRQ_ENTRY = g_quark_from_string("soft_irq_entry");
2736 LTT_EVENT_SOFT_IRQ_EXIT = g_quark_from_string("soft_irq_exit");
eed2ef37 2737 LTT_EVENT_SCHEDCHANGE = g_quark_from_string("schedchange");
2738 LTT_EVENT_FORK = g_quark_from_string("fork");
7bfd7820 2739 LTT_EVENT_KERNEL_THREAD = g_quark_from_string("kernel_thread");
eed2ef37 2740 LTT_EVENT_EXIT = g_quark_from_string("exit");
2741 LTT_EVENT_FREE = g_quark_from_string("free");
f4b88a7d 2742 LTT_EVENT_EXEC = g_quark_from_string("exec");
b3fd4c02 2743 LTT_EVENT_ENUM_PROCESS_STATE = g_quark_from_string("enumerate_process_state");
302efbad 2744 LTT_EVENT_FUNCTION_ENTRY = g_quark_from_string("function_entry");
2745 LTT_EVENT_FUNCTION_EXIT = g_quark_from_string("function_exit");
7b5f6cf1 2746 LTT_EVENT_THREAD_BRAND = g_quark_from_string("thread_brand");
eed2ef37 2747
2748
2749 LTT_FIELD_SYSCALL_ID = g_quark_from_string("syscall_id");
2750 LTT_FIELD_TRAP_ID = g_quark_from_string("trap_id");
2751 LTT_FIELD_IRQ_ID = g_quark_from_string("irq_id");
faf074a3 2752 LTT_FIELD_SOFT_IRQ_ID = g_quark_from_string("softirq_id");
eed2ef37 2753 LTT_FIELD_OUT = g_quark_from_string("out");
2754 LTT_FIELD_IN = g_quark_from_string("in");
2755 LTT_FIELD_OUT_STATE = g_quark_from_string("out_state");
2756 LTT_FIELD_PARENT_PID = g_quark_from_string("parent_pid");
2757 LTT_FIELD_CHILD_PID = g_quark_from_string("child_pid");
2758 LTT_FIELD_PID = g_quark_from_string("pid");
f4b88a7d 2759 LTT_FIELD_FILENAME = g_quark_from_string("filename");
b3fd4c02 2760 LTT_FIELD_NAME = g_quark_from_string("name");
e62e7f3a 2761 LTT_FIELD_TYPE = g_quark_from_string("type");
b3fd4c02 2762 LTT_FIELD_MODE = g_quark_from_string("mode");
2763 LTT_FIELD_SUBMODE = g_quark_from_string("submode");
2764 LTT_FIELD_STATUS = g_quark_from_string("status");
302efbad 2765 LTT_FIELD_THIS_FN = g_quark_from_string("this_fn");
2766 LTT_FIELD_CALL_SITE = g_quark_from_string("call_site");
eed2ef37 2767
ffd54a90 2768}
dc877563 2769
08b1c66e 2770static void module_destroy()
ffd54a90 2771{
2772}
dc877563 2773
2774
08b1c66e 2775LTTV_MODULE("state", "State computation", \
2776 "Update the system state, possibly saving it at intervals", \
2777 module_init, module_destroy)
2778
dc877563 2779
2780
This page took 0.187126 seconds and 4 git commands to generate.