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