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