revert the current thread change
[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 }
0292757b 1663 g_assert(child_process->name == LTTV_STATE_UNNAMED);
1664 child_process->name = process->name;
1665 child_process->brand = process->brand;
4ad73431 1666
dc877563 1667 return FALSE;
1668}
1669
7bfd7820 1670/* We stamp a newly created process as kernel_thread */
1671static gboolean process_kernel_thread(void *hook_data, void *call_data)
1672{
1673 LttvTracefileState *s = (LttvTracefileState *)call_data;
1674 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
1675 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
1676 guint pid;
ae3d0f50 1677 guint cpu = s->cpu;
7bfd7820 1678 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
1679 LttvProcessState *process;
1680 LttvExecutionState *es;
1681
1682 /* PID */
1683 pid = ltt_event_get_unsigned(e, thf->f1);
1684
1685 process = lttv_state_find_process(ts, ANY_CPU, pid);
1686 es = &g_array_index(process->execution_stack, LttvExecutionState, 0);
1687 es->t = LTTV_STATE_SYSCALL;
e62e7f3a 1688 process->type = LTTV_STATE_KERNEL_THREAD;
7bfd7820 1689
1690 return FALSE;
1691}
dc877563 1692
eed2ef37 1693static gboolean process_exit(void *hook_data, void *call_data)
dc877563 1694{
eed2ef37 1695 LttvTracefileState *s = (LttvTracefileState *)call_data;
1696 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
d052ffc3 1697 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
eed2ef37 1698 LttField *f;
1699 guint pid;
ae3d0f50 1700 guint cpu = s->cpu;
348c6ba8 1701 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
6f54e0f4 1702 LttvProcessState *process; // = ts->running_process[cpu];
eed2ef37 1703
1704 pid = ltt_event_get_unsigned(e, thf->f1);
1705
1706 // FIXME : Add this test in the "known state" section
348c6ba8 1707 // g_assert(process->pid == pid);
eed2ef37 1708
6f54e0f4 1709 process = lttv_state_find_process(ts, ANY_CPU, pid);
348c6ba8 1710 if(likely(process != NULL)) {
1711 process->state->s = LTTV_STATE_EXIT;
2cdc690b 1712 }
1713 return FALSE;
2cdc690b 1714}
1715
eed2ef37 1716static gboolean process_free(void *hook_data, void *call_data)
2da61677 1717{
eed2ef37 1718 LttvTracefileState *s = (LttvTracefileState *)call_data;
348c6ba8 1719 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
eed2ef37 1720 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
d052ffc3 1721 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
2da61677 1722 guint release_pid;
1723 LttvProcessState *process;
1724
1725 /* PID of the process to release */
eed2ef37 1726 release_pid = ltt_event_get_unsigned(e, thf->f1);
15b3d537 1727
1728 g_assert(release_pid != 0);
2da61677 1729
348c6ba8 1730 process = lttv_state_find_process(ts, ANY_CPU, release_pid);
2da61677 1731
1732 if(likely(process != NULL)) {
1733 /* release_task is happening at kernel level : we can now safely release
1734 * the data structure of the process */
5562ddce 1735 //This test is fun, though, as it may happen that
1736 //at time t : CPU 0 : process_free
1737 //at time t+150ns : CPU 1 : schedule out
1738 //Clearly due to time imprecision, we disable it. (Mathieu)
1739 //If this weird case happen, we have no choice but to put the
1740 //Currently running process on the cpu to 0.
791dffa6 1741 //I re-enable it following time precision fixes. (Mathieu)
1742 //Well, in the case where an process is freed by a process on another CPU
1743 //and still scheduled, it happens that this is the schedchange that will
1744 //drop the last reference count. Do not free it here!
0bd2f89c 1745 guint num_cpus = ltt_trace_get_num_cpu(ts->parent.t);
1746 guint i;
1747 for(i=0; i< num_cpus; i++) {
5562ddce 1748 //g_assert(process != ts->running_process[i]);
1749 if(process == ts->running_process[i]) {
791dffa6 1750 //ts->running_process[i] = lttv_state_find_process(ts, i, 0);
1751 break;
5562ddce 1752 }
0bd2f89c 1753 }
6f54e0f4 1754 if(i == num_cpus) /* process is not scheduled */
1755 exit_process(s, process);
2da61677 1756 }
1757
1758 return FALSE;
1759}
1760
f4b88a7d 1761
1762static gboolean process_exec(void *hook_data, void *call_data)
1763{
1764 LttvTracefileState *s = (LttvTracefileState *)call_data;
1765 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
1766 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
1767 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
743e50fd 1768 //gchar *name;
ae3d0f50 1769 guint cpu = s->cpu;
f4b88a7d 1770 LttvProcessState *process = ts->running_process[cpu];
1771
1772 /* PID of the process to release */
743e50fd 1773 guint64 name_len = ltt_event_field_element_number(e, thf->f1);
1774 //name = ltt_event_get_string(e, thf->f1);
f2923fb2 1775 LttField *child = ltt_event_field_element_select(e, thf->f1, 0);
1776 gchar *name_begin =
1777 (gchar*)(ltt_event_data(e)+ltt_event_field_offset(e, child));
743e50fd 1778 gchar *null_term_name = g_new(gchar, name_len+1);
1779 memcpy(null_term_name, name_begin, name_len);
1780 null_term_name[name_len] = '\0';
1781
1782 process->name = g_quark_from_string(null_term_name);
0292757b 1783 process->brand = LTTV_STATE_UNBRANDED;
f2923fb2 1784 g_free(null_term_name);
f4b88a7d 1785 return FALSE;
1786}
1787
7b5f6cf1 1788static gboolean thread_brand(void *hook_data, void *call_data)
1789{
1790 LttvTracefileState *s = (LttvTracefileState *)call_data;
1791 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
1792 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
1793 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
1794 gchar *name;
1795 guint cpu = s->cpu;
1796 LttvProcessState *process = ts->running_process[cpu];
1797
1798 name = ltt_event_get_string(e, thf->f1);
1799 process->brand = g_quark_from_string(name);
1800
1801 return FALSE;
1802}
1803
b3fd4c02 1804static gboolean enum_process_state(void *hook_data, void *call_data)
1805{
1806 LttvTracefileState *s = (LttvTracefileState *)call_data;
1807 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
1808 //It's slow : optimise later by doing this before reading trace.
1809 LttEventType *et = ltt_event_eventtype(e);
1810 //
1811 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
1812 guint parent_pid;
1813 guint pid;
1814 gchar * command;
ae3d0f50 1815 guint cpu = s->cpu;
b3fd4c02 1816 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
1817 LttvProcessState *process = ts->running_process[cpu];
1818 LttvProcessState *parent_process;
e62e7f3a 1819 LttField *f4, *f5, *f6, *f7;
1820 GQuark type, mode, submode, status;
1821 LttvExecutionState *es;
f4b88a7d 1822
b3fd4c02 1823 /* PID */
1824 pid = ltt_event_get_unsigned(e, thf->f1);
f4b88a7d 1825
b3fd4c02 1826 /* Parent PID */
1827 parent_pid = ltt_event_get_unsigned(e, thf->f2);
1828
1829 /* Command name */
1830 command = ltt_event_get_string(e, thf->f3);
1831
e62e7f3a 1832 /* type */
1833 f4 = ltt_eventtype_field_by_name(et, LTT_FIELD_TYPE);
1834 type = ltt_enum_string_get(ltt_field_type(f4),
b3fd4c02 1835 ltt_event_get_unsigned(e, f4));
1836
e62e7f3a 1837 /* mode */
1838 f5 = ltt_eventtype_field_by_name(et, LTT_FIELD_MODE);
1839 mode = ltt_enum_string_get(ltt_field_type(f5),
b3fd4c02 1840 ltt_event_get_unsigned(e, f5));
1841
e62e7f3a 1842 /* submode */
1843 f6 = ltt_eventtype_field_by_name(et, LTT_FIELD_SUBMODE);
1844 submode = ltt_enum_string_get(ltt_field_type(f6),
b3fd4c02 1845 ltt_event_get_unsigned(e, f6));
1846
e62e7f3a 1847 /* status */
1848 f7 = ltt_eventtype_field_by_name(et, LTT_FIELD_STATUS);
1849 status = ltt_enum_string_get(ltt_field_type(f7),
1850 ltt_event_get_unsigned(e, f7));
1851
b3fd4c02 1852 /* The process might exist if a process was forked while performing the sate dump. */
1853 process = lttv_state_find_process(ts, ANY_CPU, pid);
1854 if(process == NULL) {
1855 parent_process = lttv_state_find_process(ts, ANY_CPU, parent_pid);
1856 process = lttv_state_create_process(ts, parent_process, cpu,
1857 pid, g_quark_from_string(command),
1858 &s->parent.timestamp);
1859
1860 /* Keep the stack bottom : a running user mode */
ab893fb1 1861 /* Disabled because of inconsistencies in the current statedump states. */
e62e7f3a 1862 if(type == LTTV_STATE_KERNEL_THREAD) {
b3fd4c02 1863 /* Only keep the bottom */
1864 process->execution_stack = g_array_set_size(process->execution_stack, 1);
e62e7f3a 1865 es = process->state = &g_array_index(process->execution_stack,
1866 LttvExecutionState, 0);
1867 es->t = LTTV_STATE_SYSCALL;
1868 es->s = status;
1869 es->n = submode;
b3fd4c02 1870 } else {
1871 /* On top of it : */
b3fd4c02 1872 es = process->state = &g_array_index(process->execution_stack,
1873 LttvExecutionState, 1);
e62e7f3a 1874 es->t = LTTV_STATE_USER_MODE;
b3fd4c02 1875 es->s = status;
1876 es->n = submode;
1877 }
e62e7f3a 1878#if 0
ab893fb1 1879 /* UNKNOWN STATE */
1880 {
ab893fb1 1881 es = process->state = &g_array_index(process->execution_stack,
1882 LttvExecutionState, 1);
1883 es->t = LTTV_STATE_MODE_UNKNOWN;
1884 es->s = LTTV_STATE_UNNAMED;
1885 es->n = LTTV_STATE_SUBMODE_UNKNOWN;
1886 }
e62e7f3a 1887#endif //0
b3fd4c02 1888 } else {
1889 /* The process has already been created :
1890 * Probably was forked while dumping the process state or
1891 * was simply scheduled in prior to get the state dump event.
e62e7f3a 1892 * We know for sure if it is a user space thread.
b3fd4c02 1893 */
1894 process->ppid = parent_pid;
1895 process->name = g_quark_from_string(command);
e62e7f3a 1896 es = &g_array_index(process->execution_stack, LttvExecutionState, 0);
1897 if(type != LTTV_STATE_KERNEL_THREAD)
1898 es->t = LTTV_STATE_USER_MODE;
b3fd4c02 1899 /* Don't mess around with the stack, it will eventually become
1900 * ok after the end of state dump. */
1901 }
1902
1903 return FALSE;
1904}
f4b88a7d 1905
58c88a41 1906gint lttv_state_hook_add_event_hooks(void *hook_data, void *call_data)
1907{
1908 LttvTracesetState *tss = (LttvTracesetState*)(call_data);
1909
1910 lttv_state_add_event_hooks(tss);
1911
1912 return 0;
1913}
dc877563 1914
308711e5 1915void lttv_state_add_event_hooks(LttvTracesetState *self)
dc877563 1916{
ba576a78 1917 LttvTraceset *traceset = self->parent.ts;
dc877563 1918
eed2ef37 1919 guint i, j, k, l, nb_trace, nb_tracefile;
dc877563 1920
ba576a78 1921 LttvTraceState *ts;
dc877563 1922
ba576a78 1923 LttvTracefileState *tfs;
dc877563 1924
dc877563 1925 GArray *hooks;
1926
eed2ef37 1927 LttvTraceHookByFacility *thf;
1928
1929 LttvTraceHook *hook;
dc877563 1930
1931 LttvAttributeValue val;
1932
9d239bd9 1933 gint ret;
302efbad 1934 gint hn;
9d239bd9 1935
ba576a78 1936 nb_trace = lttv_traceset_number(traceset);
dc877563 1937 for(i = 0 ; i < nb_trace ; i++) {
ba576a78 1938 ts = (LttvTraceState *)self->parent.traces[i];
dc877563 1939
1940 /* Find the eventtype id for the following events and register the
1941 associated by id hooks. */
1942
7b5f6cf1 1943 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 18);
1944 hooks = g_array_set_size(hooks, 18); // Max possible number of hooks.
302efbad 1945 hn = 0;
b445142a 1946
9d239bd9 1947 ret = lttv_trace_find_hook(ts->parent.t,
f5d7967f 1948 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_ENTRY,
eed2ef37 1949 LTT_FIELD_SYSCALL_ID, 0, 0,
302efbad 1950 syscall_entry, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
1951 if(ret) hn--;
cbe7c836 1952
9d239bd9 1953 ret = lttv_trace_find_hook(ts->parent.t,
f5d7967f 1954 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_EXIT,
eed2ef37 1955 0, 0, 0,
302efbad 1956 syscall_exit, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
1957 if(ret) hn--;
cbe7c836 1958
9d239bd9 1959 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 1960 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY,
1961 LTT_FIELD_TRAP_ID, 0, 0,
302efbad 1962 trap_entry, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
1963 if(ret) hn--;
cbe7c836 1964
9d239bd9 1965 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 1966 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT,
1967 0, 0, 0,
302efbad 1968 trap_exit, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
1969 if(ret) hn--;
cbe7c836 1970
9d239bd9 1971 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 1972 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
1973 LTT_FIELD_IRQ_ID, 0, 0,
302efbad 1974 irq_entry, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
1975 if(ret) hn--;
cbe7c836 1976
9d239bd9 1977 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 1978 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
1979 0, 0, 0,
302efbad 1980 irq_exit, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
1981 if(ret) hn--;
cbe7c836 1982
faf074a3 1983 ret = lttv_trace_find_hook(ts->parent.t,
1984 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_ENTRY,
1985 LTT_FIELD_SOFT_IRQ_ID, 0, 0,
302efbad 1986 soft_irq_entry, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
1987 if(ret) hn--;
faf074a3 1988
1989 ret = lttv_trace_find_hook(ts->parent.t,
1990 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_EXIT,
1991 0, 0, 0,
302efbad 1992 soft_irq_exit, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
1993 if(ret) hn--;
faf074a3 1994
9d239bd9 1995 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 1996 LTT_FACILITY_PROCESS, LTT_EVENT_SCHEDCHANGE,
1997 LTT_FIELD_OUT, LTT_FIELD_IN, LTT_FIELD_OUT_STATE,
302efbad 1998 schedchange, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
1999 if(ret) hn--;
cbe7c836 2000
9d239bd9 2001 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 2002 LTT_FACILITY_PROCESS, LTT_EVENT_FORK,
2003 LTT_FIELD_PARENT_PID, LTT_FIELD_CHILD_PID, 0,
302efbad 2004 process_fork, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
2005 if(ret) hn--;
eed2ef37 2006
7bfd7820 2007 ret = lttv_trace_find_hook(ts->parent.t,
2008 LTT_FACILITY_PROCESS, LTT_EVENT_KERNEL_THREAD,
2009 LTT_FIELD_PID, 0, 0,
302efbad 2010 process_kernel_thread, NULL, &g_array_index(hooks, LttvTraceHook,
2011 hn++));
2012 if(ret) hn--;
7bfd7820 2013
9d239bd9 2014 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 2015 LTT_FACILITY_PROCESS, LTT_EVENT_EXIT,
2016 LTT_FIELD_PID, 0, 0,
302efbad 2017 process_exit, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
2018 if(ret) hn--;
eed2ef37 2019
9d239bd9 2020 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 2021 LTT_FACILITY_PROCESS, LTT_EVENT_FREE,
2022 LTT_FIELD_PID, 0, 0,
302efbad 2023 process_free, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
2024 if(ret) hn--;
2cdc690b 2025
f4b88a7d 2026 ret = lttv_trace_find_hook(ts->parent.t,
2027 LTT_FACILITY_FS, LTT_EVENT_EXEC,
2028 LTT_FIELD_FILENAME, 0, 0,
302efbad 2029 process_exec, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
2030 if(ret) hn--;
f4b88a7d 2031
7b5f6cf1 2032 ret = lttv_trace_find_hook(ts->parent.t,
2033 LTT_FACILITY_USER_GENERIC, LTT_EVENT_THREAD_BRAND,
2034 LTT_FIELD_NAME, 0, 0,
2035 thread_brand, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
2036 if(ret) hn--;
2037
b3fd4c02 2038 /* statedump-related hooks */
2039 ret = lttv_trace_find_hook(ts->parent.t,
2040 LTT_FACILITY_STATEDUMP, LTT_EVENT_ENUM_PROCESS_STATE,
2041 LTT_FIELD_PID, LTT_FIELD_PARENT_PID, LTT_FIELD_NAME,
302efbad 2042 enum_process_state, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
2043 if(ret) hn--;
f4b88a7d 2044
302efbad 2045 ret = lttv_trace_find_hook(ts->parent.t,
2046 LTT_FACILITY_USER_GENERIC, LTT_EVENT_FUNCTION_ENTRY,
2047 LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE, 0,
2048 function_entry, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
2049 if(ret) hn--;
2050
2051 ret = lttv_trace_find_hook(ts->parent.t,
2052 LTT_FACILITY_USER_GENERIC, LTT_EVENT_FUNCTION_EXIT,
2053 LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE, 0,
2054 function_exit, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
2055 if(ret) hn--;
2056
2057 hooks = g_array_set_size(hooks, hn);
2058
a5ba1787 2059 /* Add these hooks to each event_by_id hooks list */
dc877563 2060
eed2ef37 2061 nb_tracefile = ts->parent.tracefiles->len;
dbb7bb09 2062
dc877563 2063 for(j = 0 ; j < nb_tracefile ; j++) {
eed2ef37 2064 tfs =
9d239bd9 2065 LTTV_TRACEFILE_STATE(g_array_index(ts->parent.tracefiles,
2066 LttvTracefileContext*, j));
dc877563 2067
2068 for(k = 0 ; k < hooks->len ; k++) {
eed2ef37 2069 hook = &g_array_index(hooks, LttvTraceHook, k);
2070 for(l=0;l<hook->fac_list->len;l++) {
2071 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
2072 lttv_hooks_add(
2073 lttv_hooks_by_id_find(tfs->parent.event_by_id, thf->id),
2074 thf->h,
d052ffc3 2075 thf,
eed2ef37 2076 LTTV_PRIO_STATE);
2077 }
ffd54a90 2078 }
dc877563 2079 }
f0b795e0 2080 lttv_attribute_find(ts->parent.a, LTTV_STATE_HOOKS, LTTV_POINTER, &val);
ba576a78 2081 *(val.v_pointer) = hooks;
dc877563 2082 }
2083}
2084
58c88a41 2085gint lttv_state_hook_remove_event_hooks(void *hook_data, void *call_data)
2086{
2087 LttvTracesetState *tss = (LttvTracesetState*)(call_data);
2088
2089 lttv_state_remove_event_hooks(tss);
2090
2091 return 0;
2092}
dc877563 2093
308711e5 2094void lttv_state_remove_event_hooks(LttvTracesetState *self)
dc877563 2095{
ba576a78 2096 LttvTraceset *traceset = self->parent.ts;
dc877563 2097
eed2ef37 2098 guint i, j, k, l, nb_trace, nb_tracefile;
dc877563 2099
ba576a78 2100 LttvTraceState *ts;
dc877563 2101
ba576a78 2102 LttvTracefileState *tfs;
dc877563 2103
dc877563 2104 GArray *hooks;
2105
eed2ef37 2106 LttvTraceHook *hook;
2107
2108 LttvTraceHookByFacility *thf;
dc877563 2109
2110 LttvAttributeValue val;
2111
ba576a78 2112 nb_trace = lttv_traceset_number(traceset);
dc877563 2113 for(i = 0 ; i < nb_trace ; i++) {
021eeb41 2114 ts = LTTV_TRACE_STATE(self->parent.traces[i]);
f0b795e0 2115 lttv_attribute_find(ts->parent.a, LTTV_STATE_HOOKS, LTTV_POINTER, &val);
ba576a78 2116 hooks = *(val.v_pointer);
dc877563 2117
a5ba1787 2118 /* Remove these hooks from each event_by_id hooks list */
dc877563 2119
eed2ef37 2120 nb_tracefile = ts->parent.tracefiles->len;
dbb7bb09 2121
dc877563 2122 for(j = 0 ; j < nb_tracefile ; j++) {
eed2ef37 2123 tfs =
cb03932a 2124 LTTV_TRACEFILE_STATE(g_array_index(ts->parent.tracefiles,
2125 LttvTracefileContext*, j));
dc877563 2126
2127 for(k = 0 ; k < hooks->len ; k++) {
eed2ef37 2128 hook = &g_array_index(hooks, LttvTraceHook, k);
2129 for(l=0;l<hook->fac_list->len;l++) {
2130 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
2131
2132 lttv_hooks_remove_data(
2133 lttv_hooks_by_id_find(tfs->parent.event_by_id, thf->id),
2134 thf->h,
d052ffc3 2135 thf);
eed2ef37 2136 }
ffd54a90 2137 }
dc877563 2138 }
1986f254 2139 for(k = 0 ; k < hooks->len ; k++)
2140 lttv_trace_hook_destroy(&g_array_index(hooks, LttvTraceHook, k));
dc877563 2141 g_array_free(hooks, TRUE);
2142 }
2143}
2144
eed2ef37 2145static gboolean state_save_event_hook(void *hook_data, void *call_data)
2146{
2147 guint *event_count = (guint*)hook_data;
2148
2149 /* Only save at LTTV_STATE_SAVE_INTERVAL */
2150 if(likely((*event_count)++ < LTTV_STATE_SAVE_INTERVAL))
2151 return FALSE;
2152 else
18c87975 2153 *event_count = 0;
eed2ef37 2154
2155 LttvTracefileState *self = (LttvTracefileState *)call_data;
2156
2157 LttvTracefileState *tfcs;
2158
2159 LttvTraceState *tcs = (LttvTraceState *)(self->parent.t_context);
2160
2161 LttEventPosition *ep;
2162
2163 guint i;
2164
2165 LttTracefile *tf;
2166
2167 LttvAttribute *saved_states_tree, *saved_state_tree;
2168
2169 LttvAttributeValue value;
2170
2171 saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a,
2172 LTTV_STATE_SAVED_STATES);
2173 saved_state_tree = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
2174 value = lttv_attribute_add(saved_states_tree,
2175 lttv_attribute_get_number(saved_states_tree), LTTV_GOBJECT);
2176 *(value.v_gobject) = (GObject *)saved_state_tree;
2177 value = lttv_attribute_add(saved_state_tree, LTTV_STATE_TIME, LTTV_TIME);
2178 *(value.v_time) = self->parent.timestamp;
2179 lttv_state_save(tcs, saved_state_tree);
2180 g_debug("Saving state at time %lu.%lu", self->parent.timestamp.tv_sec,
2181 self->parent.timestamp.tv_nsec);
2182
2183 *(tcs->max_time_state_recomputed_in_seek) = self->parent.timestamp;
2184
2185 return FALSE;
2186}
2187
14aecf75 2188static gboolean state_save_after_trace_hook(void *hook_data, void *call_data)
2189{
2190 LttvTraceState *tcs = (LttvTraceState *)(call_data);
2191
2192 *(tcs->max_time_state_recomputed_in_seek) = tcs->parent.time_span.end_time;
2193
2194 return FALSE;
2195}
2196
ae3d0f50 2197guint lttv_state_current_cpu(LttvTracefileState *tfs)
2198{
2199 return tfs->cpu;
2200}
2201
2202
2203
eed2ef37 2204#if 0
08b1c66e 2205static gboolean block_start(void *hook_data, void *call_data)
308711e5 2206{
dbb7bb09 2207 LttvTracefileState *self = (LttvTracefileState *)call_data;
308711e5 2208
dbb7bb09 2209 LttvTracefileState *tfcs;
308711e5 2210
dbb7bb09 2211 LttvTraceState *tcs = (LttvTraceState *)(self->parent.t_context);
2212
2213 LttEventPosition *ep;
308711e5 2214
dbb7bb09 2215 guint i, nb_block, nb_event, nb_tracefile;
308711e5 2216
2217 LttTracefile *tf;
2218
2219 LttvAttribute *saved_states_tree, *saved_state_tree;
2220
2221 LttvAttributeValue value;
2222
dbb7bb09 2223 ep = ltt_event_position_new();
eed2ef37 2224
2225 nb_tracefile = tcs->parent.tracefiles->len;
dbb7bb09 2226
2227 /* Count the number of events added since the last block end in any
2228 tracefile. */
2229
2230 for(i = 0 ; i < nb_tracefile ; i++) {
eed2ef37 2231 tfcs =
2232 LTTV_TRACEFILE_STATE(&g_array_index(tcs->parent.tracefiles,
2233 LttvTracefileContext, i));
dbb7bb09 2234 ltt_event_position(tfcs->parent.e, ep);
2235 ltt_event_position_get(ep, &nb_block, &nb_event, &tf);
2236 tcs->nb_event += nb_event - tfcs->saved_position;
2237 tfcs->saved_position = nb_event;
2238 }
2239 g_free(ep);
308711e5 2240
308711e5 2241 if(tcs->nb_event >= tcs->save_interval) {
2242 saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a,
2243 LTTV_STATE_SAVED_STATES);
2244 saved_state_tree = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
2245 value = lttv_attribute_add(saved_states_tree,
2246 lttv_attribute_get_number(saved_states_tree), LTTV_GOBJECT);
2247 *(value.v_gobject) = (GObject *)saved_state_tree;
2248 value = lttv_attribute_add(saved_state_tree, LTTV_STATE_TIME, LTTV_TIME);
dbb7bb09 2249 *(value.v_time) = self->parent.timestamp;
308711e5 2250 lttv_state_save(tcs, saved_state_tree);
2251 tcs->nb_event = 0;
08b1c66e 2252 g_debug("Saving state at time %lu.%lu", self->parent.timestamp.tv_sec,
2253 self->parent.timestamp.tv_nsec);
308711e5 2254 }
dbb7bb09 2255 *(tcs->max_time_state_recomputed_in_seek) = self->parent.timestamp;
308711e5 2256 return FALSE;
2257}
eed2ef37 2258#endif //0
308711e5 2259
eed2ef37 2260#if 0
08b1c66e 2261static gboolean block_end(void *hook_data, void *call_data)
2262{
2263 LttvTracefileState *self = (LttvTracefileState *)call_data;
2264
2265 LttvTraceState *tcs = (LttvTraceState *)(self->parent.t_context);
2266
2267 LttTracefile *tf;
2268
2269 LttEventPosition *ep;
2270
2271 guint nb_block, nb_event;
2272
2273 ep = ltt_event_position_new();
2274 ltt_event_position(self->parent.e, ep);
2275 ltt_event_position_get(ep, &nb_block, &nb_event, &tf);
2276 tcs->nb_event += nb_event - self->saved_position + 1;
2277 self->saved_position = 0;
2278 *(tcs->max_time_state_recomputed_in_seek) = self->parent.timestamp;
2279 g_free(ep);
00e74b69 2280
2281 return FALSE;
08b1c66e 2282}
eed2ef37 2283#endif //0
2284#if 0
308711e5 2285void lttv_state_save_add_event_hooks(LttvTracesetState *self)
2286{
2287 LttvTraceset *traceset = self->parent.ts;
2288
00e74b69 2289 guint i, j, nb_trace, nb_tracefile;
308711e5 2290
2291 LttvTraceState *ts;
2292
2293 LttvTracefileState *tfs;
2294
08b1c66e 2295 LttvTraceHook hook_start, hook_end;
308711e5 2296
2297 nb_trace = lttv_traceset_number(traceset);
2298 for(i = 0 ; i < nb_trace ; i++) {
2299 ts = (LttvTraceState *)self->parent.traces[i];
eed2ef37 2300
08b1c66e 2301 lttv_trace_find_hook(ts->parent.t, "core","block_start",NULL,
2302 NULL, NULL, block_start, &hook_start);
308711e5 2303 lttv_trace_find_hook(ts->parent.t, "core","block_end",NULL,
08b1c66e 2304 NULL, NULL, block_end, &hook_end);
308711e5 2305
eed2ef37 2306 nb_tracefile = ts->parent.tracefiles->len;
308711e5 2307
dbb7bb09 2308 for(j = 0 ; j < nb_tracefile ; j++) {
eed2ef37 2309 tfs =
2310 LTTV_TRACEFILE_STATE(&g_array_index(ts->parent.tracefiles,
2311 LttvTracefileContext, j));
a5ba1787 2312 lttv_hooks_add(lttv_hooks_by_id_find(tfs->parent.event_by_id,
eed2ef37 2313 hook_start.id), hook_start.h, NULL, LTTV_PRIO_STATE);
a5ba1787 2314 lttv_hooks_add(lttv_hooks_by_id_find(tfs->parent.event_by_id,
eed2ef37 2315 hook_end.id), hook_end.h, NULL, LTTV_PRIO_STATE);
2316 }
2317 }
2318}
2319#endif //0
2320
2321void lttv_state_save_add_event_hooks(LttvTracesetState *self)
2322{
2323 LttvTraceset *traceset = self->parent.ts;
2324
2325 guint i, j, nb_trace, nb_tracefile;
2326
2327 LttvTraceState *ts;
2328
2329 LttvTracefileState *tfs;
2330
2331
2332 nb_trace = lttv_traceset_number(traceset);
2333 for(i = 0 ; i < nb_trace ; i++) {
2334
2335 ts = (LttvTraceState *)self->parent.traces[i];
2336 nb_tracefile = ts->parent.tracefiles->len;
2337
3054461a 2338 guint *event_count = g_new(guint, 1);
2339 *event_count = 0;
2340
eed2ef37 2341 for(j = 0 ; j < nb_tracefile ; j++) {
2342 tfs =
cb03932a 2343 LTTV_TRACEFILE_STATE(g_array_index(ts->parent.tracefiles,
2344 LttvTracefileContext*, j));
eed2ef37 2345 lttv_hooks_add(tfs->parent.event,
2346 state_save_event_hook,
2347 event_count,
2348 LTTV_PRIO_STATE);
2349
308711e5 2350 }
2351 }
14aecf75 2352
2353 lttv_process_traceset_begin(&self->parent,
2354 NULL, NULL, NULL, NULL, NULL);
2355
308711e5 2356}
2357
b56b5fec 2358gint lttv_state_save_hook_add_event_hooks(void *hook_data, void *call_data)
2359{
2360 LttvTracesetState *tss = (LttvTracesetState*)(call_data);
2361
2362 lttv_state_save_add_event_hooks(tss);
2363
2364 return 0;
2365}
2366
308711e5 2367
eed2ef37 2368#if 0
308711e5 2369void lttv_state_save_remove_event_hooks(LttvTracesetState *self)
2370{
2371 LttvTraceset *traceset = self->parent.ts;
2372
00e74b69 2373 guint i, j, nb_trace, nb_tracefile;
308711e5 2374
2375 LttvTraceState *ts;
2376
2377 LttvTracefileState *tfs;
2378
08b1c66e 2379 LttvTraceHook hook_start, hook_end;
308711e5 2380
2381 nb_trace = lttv_traceset_number(traceset);
2382 for(i = 0 ; i < nb_trace ; i++) {
2383 ts = LTTV_TRACE_STATE(self->parent.traces[i]);
eed2ef37 2384
08b1c66e 2385 lttv_trace_find_hook(ts->parent.t, "core","block_start",NULL,
2386 NULL, NULL, block_start, &hook_start);
2387
308711e5 2388 lttv_trace_find_hook(ts->parent.t, "core","block_end",NULL,
08b1c66e 2389 NULL, NULL, block_end, &hook_end);
308711e5 2390
eed2ef37 2391 nb_tracefile = ts->parent.tracefiles->len;
308711e5 2392
dbb7bb09 2393 for(j = 0 ; j < nb_tracefile ; j++) {
eed2ef37 2394 tfs =
2395 LTTV_TRACEFILE_STATE(&g_array_index(ts->parent.tracefiles,
2396 LttvTracefileContext, j));
308711e5 2397 lttv_hooks_remove_data(lttv_hooks_by_id_find(
a5ba1787 2398 tfs->parent.event_by_id, hook_start.id), hook_start.h, NULL);
08b1c66e 2399 lttv_hooks_remove_data(lttv_hooks_by_id_find(
a5ba1787 2400 tfs->parent.event_by_id, hook_end.id), hook_end.h, NULL);
308711e5 2401 }
2402 }
2403}
eed2ef37 2404#endif //0
2405
2406void lttv_state_save_remove_event_hooks(LttvTracesetState *self)
2407{
2408 LttvTraceset *traceset = self->parent.ts;
2409
2410 guint i, j, nb_trace, nb_tracefile;
2411
2412 LttvTraceState *ts;
2413
2414 LttvTracefileState *tfs;
2415
14aecf75 2416 LttvHooks *after_trace = lttv_hooks_new();
2417
2418 lttv_hooks_add(after_trace,
2419 state_save_after_trace_hook,
2420 NULL,
2421 LTTV_PRIO_STATE);
2422
2423
2424 lttv_process_traceset_end(&self->parent,
2425 NULL, after_trace, NULL, NULL, NULL);
eed2ef37 2426
14aecf75 2427 lttv_hooks_destroy(after_trace);
2428
eed2ef37 2429 nb_trace = lttv_traceset_number(traceset);
2430 for(i = 0 ; i < nb_trace ; i++) {
2431
2432 ts = (LttvTraceState *)self->parent.traces[i];
2433 nb_tracefile = ts->parent.tracefiles->len;
2434
22b165e9 2435 guint *event_count = NULL;
eed2ef37 2436
2437 for(j = 0 ; j < nb_tracefile ; j++) {
2438 tfs =
cb03932a 2439 LTTV_TRACEFILE_STATE(g_array_index(ts->parent.tracefiles,
2440 LttvTracefileContext*, j));
eed2ef37 2441 event_count = lttv_hooks_remove(tfs->parent.event,
2442 state_save_event_hook);
eed2ef37 2443 }
22b165e9 2444 if(event_count) g_free(event_count);
eed2ef37 2445 }
2446}
308711e5 2447
b56b5fec 2448gint lttv_state_save_hook_remove_event_hooks(void *hook_data, void *call_data)
2449{
2450 LttvTracesetState *tss = (LttvTracesetState*)(call_data);
2451
2452 lttv_state_save_remove_event_hooks(tss);
2453
2454 return 0;
2455}
308711e5 2456
dd025f91 2457void lttv_state_traceset_seek_time_closest(LttvTracesetState *self, LttTime t)
308711e5 2458{
2459 LttvTraceset *traceset = self->parent.ts;
2460
00e74b69 2461 guint i, nb_trace;
308711e5 2462
2463 int min_pos, mid_pos, max_pos;
2464
728d0c3e 2465 guint call_rest = 0;
2466
308711e5 2467 LttvTraceState *tcs;
2468
2469 LttvAttributeValue value;
2470
2471 LttvAttributeType type;
2472
2473 LttvAttributeName name;
2474
c0cb4d12 2475 gboolean is_named;
2476
308711e5 2477 LttvAttribute *saved_states_tree, *saved_state_tree, *closest_tree;
2478
d448fce2 2479 //g_tree_destroy(self->parent.pqueue);
2480 //self->parent.pqueue = g_tree_new(compare_tracefile);
348c6ba8 2481
728d0c3e 2482 g_info("Entering seek_time_closest for time %lu.%lu", t.tv_sec, t.tv_nsec);
2483
308711e5 2484 nb_trace = lttv_traceset_number(traceset);
2485 for(i = 0 ; i < nb_trace ; i++) {
2486 tcs = (LttvTraceState *)self->parent.traces[i];
2487
2a2fa4f0 2488 if(ltt_time_compare(t, *(tcs->max_time_state_recomputed_in_seek)) < 0) {
2489 saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a,
2490 LTTV_STATE_SAVED_STATES);
2491 min_pos = -1;
2492
2493 if(saved_states_tree) {
dd025f91 2494 max_pos = lttv_attribute_get_number(saved_states_tree) - 1;
2495 mid_pos = max_pos / 2;
2496 while(min_pos < max_pos) {
c0cb4d12 2497 type = lttv_attribute_get(saved_states_tree, mid_pos, &name, &value,
2498 &is_named);
dd025f91 2499 g_assert(type == LTTV_GOBJECT);
2500 saved_state_tree = *((LttvAttribute **)(value.v_gobject));
2501 type = lttv_attribute_get_by_name(saved_state_tree, LTTV_STATE_TIME,
2502 &value);
2503 g_assert(type == LTTV_TIME);
2504 if(ltt_time_compare(*(value.v_time), t) < 0) {
2505 min_pos = mid_pos;
2506 closest_tree = saved_state_tree;
2507 }
2508 else max_pos = mid_pos - 1;
2509
2510 mid_pos = (min_pos + max_pos + 1) / 2;
2511 }
2a2fa4f0 2512 }
dd025f91 2513
2a2fa4f0 2514 /* restore the closest earlier saved state */
f95bc830 2515 if(min_pos != -1) {
2516 lttv_state_restore(tcs, closest_tree);
728d0c3e 2517 call_rest = 1;
f95bc830 2518 }
dd025f91 2519
2a2fa4f0 2520 /* There is no saved state, yet we want to have it. Restart at T0 */
dd025f91 2521 else {
2522 restore_init_state(tcs);
2523 lttv_process_trace_seek_time(&(tcs->parent), ltt_time_zero);
308711e5 2524 }
9444deae 2525 }
dd025f91 2526 /* We want to seek quickly without restoring/updating the state */
2527 else {
308711e5 2528 restore_init_state(tcs);
dd025f91 2529 lttv_process_trace_seek_time(&(tcs->parent), t);
308711e5 2530 }
308711e5 2531 }
728d0c3e 2532 if(!call_rest) g_info("NOT Calling restore");
308711e5 2533}
2534
2535
2536static void
2537traceset_state_instance_init (GTypeInstance *instance, gpointer g_class)
2538{
2539}
2540
2541
2542static void
2543traceset_state_finalize (LttvTracesetState *self)
2544{
2545 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))->
2546 finalize(G_OBJECT(self));
2547}
2548
2549
2550static void
2551traceset_state_class_init (LttvTracesetContextClass *klass)
2552{
2553 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
2554
2555 gobject_class->finalize = (void (*)(GObject *self)) traceset_state_finalize;
2556 klass->init = (void (*)(LttvTracesetContext *self, LttvTraceset *ts))init;
2557 klass->fini = (void (*)(LttvTracesetContext *self))fini;
2558 klass->new_traceset_context = new_traceset_context;
2559 klass->new_trace_context = new_trace_context;
2560 klass->new_tracefile_context = new_tracefile_context;
2561}
2562
2563
2564GType
2565lttv_traceset_state_get_type(void)
2566{
2567 static GType type = 0;
2568 if (type == 0) {
2569 static const GTypeInfo info = {
2570 sizeof (LttvTracesetStateClass),
2571 NULL, /* base_init */
2572 NULL, /* base_finalize */
2573 (GClassInitFunc) traceset_state_class_init, /* class_init */
2574 NULL, /* class_finalize */
2575 NULL, /* class_data */
dbb7bb09 2576 sizeof (LttvTracesetState),
308711e5 2577 0, /* n_preallocs */
00e74b69 2578 (GInstanceInitFunc) traceset_state_instance_init, /* instance_init */
2579 NULL /* value handling */
308711e5 2580 };
2581
2582 type = g_type_register_static (LTTV_TRACESET_CONTEXT_TYPE, "LttvTracesetStateType",
2583 &info, 0);
2584 }
2585 return type;
2586}
2587
2588
2589static void
2590trace_state_instance_init (GTypeInstance *instance, gpointer g_class)
2591{
2592}
2593
2594
2595static void
2596trace_state_finalize (LttvTraceState *self)
2597{
2598 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_CONTEXT_TYPE))->
2599 finalize(G_OBJECT(self));
2600}
2601
2602
2603static void
2604trace_state_class_init (LttvTraceStateClass *klass)
2605{
2606 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
2607
2608 gobject_class->finalize = (void (*)(GObject *self)) trace_state_finalize;
2609 klass->state_save = state_save;
2610 klass->state_restore = state_restore;
2611 klass->state_saved_free = state_saved_free;
2612}
2613
2614
2615GType
2616lttv_trace_state_get_type(void)
2617{
2618 static GType type = 0;
2619 if (type == 0) {
2620 static const GTypeInfo info = {
2621 sizeof (LttvTraceStateClass),
2622 NULL, /* base_init */
2623 NULL, /* base_finalize */
2624 (GClassInitFunc) trace_state_class_init, /* class_init */
2625 NULL, /* class_finalize */
2626 NULL, /* class_data */
2627 sizeof (LttvTraceState),
2628 0, /* n_preallocs */
00e74b69 2629 (GInstanceInitFunc) trace_state_instance_init, /* instance_init */
2630 NULL /* value handling */
308711e5 2631 };
2632
2633 type = g_type_register_static (LTTV_TRACE_CONTEXT_TYPE,
2634 "LttvTraceStateType", &info, 0);
2635 }
2636 return type;
2637}
2638
2639
2640static void
2641tracefile_state_instance_init (GTypeInstance *instance, gpointer g_class)
2642{
2643}
2644
2645
2646static void
2647tracefile_state_finalize (LttvTracefileState *self)
2648{
2649 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_CONTEXT_TYPE))->
2650 finalize(G_OBJECT(self));
2651}
2652
2653
2654static void
2655tracefile_state_class_init (LttvTracefileStateClass *klass)
2656{
2657 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
2658
2659 gobject_class->finalize = (void (*)(GObject *self)) tracefile_state_finalize;
2660}
2661
2662
2663GType
2664lttv_tracefile_state_get_type(void)
2665{
2666 static GType type = 0;
2667 if (type == 0) {
2668 static const GTypeInfo info = {
2669 sizeof (LttvTracefileStateClass),
2670 NULL, /* base_init */
2671 NULL, /* base_finalize */
2672 (GClassInitFunc) tracefile_state_class_init, /* class_init */
2673 NULL, /* class_finalize */
2674 NULL, /* class_data */
2675 sizeof (LttvTracefileState),
2676 0, /* n_preallocs */
00e74b69 2677 (GInstanceInitFunc) tracefile_state_instance_init, /* instance_init */
2678 NULL /* value handling */
308711e5 2679 };
2680
2681 type = g_type_register_static (LTTV_TRACEFILE_CONTEXT_TYPE,
2682 "LttvTracefileStateType", &info, 0);
2683 }
2684 return type;
2685}
2686
2687
08b1c66e 2688static void module_init()
ffd54a90 2689{
83e160f2 2690 LTTV_STATE_UNNAMED = g_quark_from_string("UNNAMED");
7b5f6cf1 2691 LTTV_STATE_UNBRANDED = g_quark_from_string("UNBRANDED");
b3fd4c02 2692 LTTV_STATE_MODE_UNKNOWN = g_quark_from_string("MODE_UNKNOWN");
2693 LTTV_STATE_USER_MODE = g_quark_from_string("USER_MODE");
2694 LTTV_STATE_SYSCALL = g_quark_from_string("SYSCALL");
2695 LTTV_STATE_TRAP = g_quark_from_string("TRAP");
2696 LTTV_STATE_IRQ = g_quark_from_string("IRQ");
2697 LTTV_STATE_SOFT_IRQ = g_quark_from_string("SOFTIRQ");
2698 LTTV_STATE_SUBMODE_UNKNOWN = g_quark_from_string("UNKNOWN");
2699 LTTV_STATE_SUBMODE_NONE = g_quark_from_string("NONE");
2700 LTTV_STATE_WAIT_FORK = g_quark_from_string("WAIT_FORK");
2701 LTTV_STATE_WAIT_CPU = g_quark_from_string("WAIT_CPU");
2702 LTTV_STATE_EXIT = g_quark_from_string("EXIT");
2703 LTTV_STATE_ZOMBIE = g_quark_from_string("ZOMBIE");
2704 LTTV_STATE_WAIT = g_quark_from_string("WAIT");
2705 LTTV_STATE_RUN = g_quark_from_string("RUN");
2706 LTTV_STATE_DEAD = g_quark_from_string("DEAD");
e62e7f3a 2707 LTTV_STATE_USER_THREAD = g_quark_from_string("USER_THREAD");
2708 LTTV_STATE_KERNEL_THREAD = g_quark_from_string("KERNEL_THREAD");
308711e5 2709 LTTV_STATE_TRACEFILES = g_quark_from_string("tracefiles");
2710 LTTV_STATE_PROCESSES = g_quark_from_string("processes");
2711 LTTV_STATE_PROCESS = g_quark_from_string("process");
348c6ba8 2712 LTTV_STATE_RUNNING_PROCESS = g_quark_from_string("running_process");
308711e5 2713 LTTV_STATE_EVENT = g_quark_from_string("event");
2714 LTTV_STATE_SAVED_STATES = g_quark_from_string("saved states");
dbb7bb09 2715 LTTV_STATE_SAVED_STATES_TIME = g_quark_from_string("saved states time");
308711e5 2716 LTTV_STATE_TIME = g_quark_from_string("time");
ffd54a90 2717 LTTV_STATE_HOOKS = g_quark_from_string("saved state hooks");
f95bc830 2718 LTTV_STATE_NAME_TABLES = g_quark_from_string("name tables");
2719 LTTV_STATE_TRACE_STATE_USE_COUNT =
2720 g_quark_from_string("trace_state_use_count");
eed2ef37 2721
2722
2723 LTT_FACILITY_KERNEL = g_quark_from_string("kernel");
f5d7967f 2724 LTT_FACILITY_KERNEL_ARCH = g_quark_from_string("kernel_arch");
eed2ef37 2725 LTT_FACILITY_PROCESS = g_quark_from_string("process");
f4b88a7d 2726 LTT_FACILITY_FS = g_quark_from_string("fs");
b3fd4c02 2727 LTT_FACILITY_STATEDUMP = g_quark_from_string("statedump");
302efbad 2728 LTT_FACILITY_USER_GENERIC = g_quark_from_string("user_generic");
eed2ef37 2729
2730
2731 LTT_EVENT_SYSCALL_ENTRY = g_quark_from_string("syscall_entry");
2732 LTT_EVENT_SYSCALL_EXIT = g_quark_from_string("syscall_exit");
2733 LTT_EVENT_TRAP_ENTRY = g_quark_from_string("trap_entry");
2734 LTT_EVENT_TRAP_EXIT = g_quark_from_string("trap_exit");
2735 LTT_EVENT_IRQ_ENTRY = g_quark_from_string("irq_entry");
2736 LTT_EVENT_IRQ_EXIT = g_quark_from_string("irq_exit");
faf074a3 2737 LTT_EVENT_SOFT_IRQ_ENTRY = g_quark_from_string("soft_irq_entry");
2738 LTT_EVENT_SOFT_IRQ_EXIT = g_quark_from_string("soft_irq_exit");
eed2ef37 2739 LTT_EVENT_SCHEDCHANGE = g_quark_from_string("schedchange");
2740 LTT_EVENT_FORK = g_quark_from_string("fork");
7bfd7820 2741 LTT_EVENT_KERNEL_THREAD = g_quark_from_string("kernel_thread");
eed2ef37 2742 LTT_EVENT_EXIT = g_quark_from_string("exit");
2743 LTT_EVENT_FREE = g_quark_from_string("free");
f4b88a7d 2744 LTT_EVENT_EXEC = g_quark_from_string("exec");
b3fd4c02 2745 LTT_EVENT_ENUM_PROCESS_STATE = g_quark_from_string("enumerate_process_state");
302efbad 2746 LTT_EVENT_FUNCTION_ENTRY = g_quark_from_string("function_entry");
2747 LTT_EVENT_FUNCTION_EXIT = g_quark_from_string("function_exit");
7b5f6cf1 2748 LTT_EVENT_THREAD_BRAND = g_quark_from_string("thread_brand");
eed2ef37 2749
2750
2751 LTT_FIELD_SYSCALL_ID = g_quark_from_string("syscall_id");
2752 LTT_FIELD_TRAP_ID = g_quark_from_string("trap_id");
2753 LTT_FIELD_IRQ_ID = g_quark_from_string("irq_id");
faf074a3 2754 LTT_FIELD_SOFT_IRQ_ID = g_quark_from_string("softirq_id");
eed2ef37 2755 LTT_FIELD_OUT = g_quark_from_string("out");
2756 LTT_FIELD_IN = g_quark_from_string("in");
2757 LTT_FIELD_OUT_STATE = g_quark_from_string("out_state");
2758 LTT_FIELD_PARENT_PID = g_quark_from_string("parent_pid");
2759 LTT_FIELD_CHILD_PID = g_quark_from_string("child_pid");
2760 LTT_FIELD_PID = g_quark_from_string("pid");
f4b88a7d 2761 LTT_FIELD_FILENAME = g_quark_from_string("filename");
b3fd4c02 2762 LTT_FIELD_NAME = g_quark_from_string("name");
e62e7f3a 2763 LTT_FIELD_TYPE = g_quark_from_string("type");
b3fd4c02 2764 LTT_FIELD_MODE = g_quark_from_string("mode");
2765 LTT_FIELD_SUBMODE = g_quark_from_string("submode");
2766 LTT_FIELD_STATUS = g_quark_from_string("status");
302efbad 2767 LTT_FIELD_THIS_FN = g_quark_from_string("this_fn");
2768 LTT_FIELD_CALL_SITE = g_quark_from_string("call_site");
eed2ef37 2769
ffd54a90 2770}
dc877563 2771
08b1c66e 2772static void module_destroy()
ffd54a90 2773{
2774}
dc877563 2775
2776
08b1c66e 2777LTTV_MODULE("state", "State computation", \
2778 "Update the system state, possibly saving it at intervals", \
2779 module_init, module_destroy)
2780
dc877563 2781
2782
This page took 0.189287 seconds and 4 git commands to generate.