usertrace update for powerpc
[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;
7cd289b0 829 guint nb_syscalls;
f95bc830 830 GQuark *trap_names;
831 GQuark *irq_names;
faf074a3 832 GQuark *soft_irq_names;
f95bc830 833} LttvNameTables;
834
835
b445142a 836static void
f95bc830 837create_name_tables(LttvTraceState *tcs)
b445142a 838{
839 int i, nb;
dc877563 840
eed2ef37 841 GQuark f_name, e_name;
842
021eeb41 843 LttvTraceHook h;
dc877563 844
eed2ef37 845 LttvTraceHookByFacility *thf;
b445142a 846
847 LttEventType *et;
848
849 LttType *t;
850
851 GString *fe_name = g_string_new("");
852
f95bc830 853 LttvNameTables *name_tables = g_new(LttvNameTables, 1);
854
855 LttvAttributeValue v;
856
857 lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_NAME_TABLES,
858 LTTV_POINTER, &v);
859 g_assert(*(v.v_pointer) == NULL);
860 *(v.v_pointer) = name_tables;
eed2ef37 861#if 0 // Use iteration over the facilities_by_name and then list all event
862 // types of each facility
b445142a 863 nb = ltt_trace_eventtype_number(tcs->parent.t);
f95bc830 864 name_tables->eventtype_names = g_new(GQuark, nb);
b445142a 865 for(i = 0 ; i < nb ; i++) {
866 et = ltt_trace_eventtype_get(tcs->parent.t, i);
867 e_name = ltt_eventtype_name(et);
868 f_name = ltt_facility_name(ltt_eventtype_facility(et));
869 g_string_printf(fe_name, "%s.%s", f_name, e_name);
f95bc830 870 name_tables->eventtype_names[i] = g_quark_from_string(fe_name->str);
b445142a 871 }
eed2ef37 872#endif //0
285468d4 873 if(!lttv_trace_find_hook(tcs->parent.t,
f5d7967f 874 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_ENTRY,
eed2ef37 875 LTT_FIELD_SYSCALL_ID, 0, 0,
285468d4 876 NULL, NULL, &h)) {
877
878 thf = lttv_trace_hook_get_first(&h);
879
880 t = ltt_field_type(thf->f1);
881 nb = ltt_type_element_number(t);
882
883 lttv_trace_hook_destroy(&h);
884
885 name_tables->syscall_names = g_new(GQuark, nb);
886 name_tables->nb_syscalls = nb;
887
888 for(i = 0 ; i < nb ; i++) {
889 name_tables->syscall_names[i] = ltt_enum_string_get(t, i);
890 }
891
892 //name_tables->syscall_names = g_new(GQuark, 256);
893 //for(i = 0 ; i < 256 ; i++) {
894 // g_string_printf(fe_name, "syscall %d", i);
895 // name_tables->syscall_names[i] = g_quark_from_string(fe_name->str);
896 //}
897 } else {
898 name_tables->syscall_names = NULL;
899 name_tables->nb_syscalls = 0;
900 }
901
902 if(!lttv_trace_find_hook(tcs->parent.t, LTT_FACILITY_KERNEL,
eed2ef37 903 LTT_EVENT_TRAP_ENTRY,
904 LTT_FIELD_TRAP_ID, 0, 0,
285468d4 905 NULL, NULL, &h)) {
eed2ef37 906
285468d4 907 thf = lttv_trace_hook_get_first(&h);
eed2ef37 908
285468d4 909 t = ltt_field_type(thf->f1);
910 //nb = ltt_type_element_number(t);
b445142a 911
285468d4 912 lttv_trace_hook_destroy(&h);
eed2ef37 913
285468d4 914 /*
915 name_tables->trap_names = g_new(GQuark, nb);
916 for(i = 0 ; i < nb ; i++) {
917 name_tables->trap_names[i] = g_quark_from_string(
918 ltt_enum_string_get(t, i));
919 }
920 */
b445142a 921
285468d4 922 name_tables->trap_names = g_new(GQuark, 256);
923 for(i = 0 ; i < 256 ; i++) {
924 g_string_printf(fe_name, "trap %d", i);
925 name_tables->trap_names[i] = g_quark_from_string(fe_name->str);
926 }
927 } else {
928 name_tables->trap_names = NULL;
929 }
b445142a 930
285468d4 931 if(!lttv_trace_find_hook(tcs->parent.t,
eed2ef37 932 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
933 LTT_FIELD_IRQ_ID, 0, 0,
285468d4 934 NULL, NULL, &h)) {
935
936 thf = lttv_trace_hook_get_first(&h);
937
938 t = ltt_field_type(thf->f1);
939 //nb = ltt_type_element_number(t);
940
941 lttv_trace_hook_destroy(&h);
942
943 /*
944 name_tables->irq_names = g_new(GQuark, nb);
945 for(i = 0 ; i < nb ; i++) {
946 name_tables->irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
947 }
948 */
949
950 name_tables->irq_names = g_new(GQuark, 256);
951 for(i = 0 ; i < 256 ; i++) {
952 g_string_printf(fe_name, "irq %d", i);
953 name_tables->irq_names[i] = g_quark_from_string(fe_name->str);
954 }
955 } else {
956 name_tables->irq_names = NULL;
957 }
faf074a3 958 /*
959 name_tables->soft_irq_names = g_new(GQuark, nb);
960 for(i = 0 ; i < nb ; i++) {
961 name_tables->soft_irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
962 }
963 */
964
965 name_tables->soft_irq_names = g_new(GQuark, 256);
966 for(i = 0 ; i < 256 ; i++) {
967 g_string_printf(fe_name, "softirq %d", i);
968 name_tables->soft_irq_names[i] = g_quark_from_string(fe_name->str);
969 }
970
971
b445142a 972 g_string_free(fe_name, TRUE);
973}
974
975
f95bc830 976static void
977get_name_tables(LttvTraceState *tcs)
978{
979 LttvNameTables *name_tables;
980
981 LttvAttributeValue v;
982
983 lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_NAME_TABLES,
984 LTTV_POINTER, &v);
985 g_assert(*(v.v_pointer) != NULL);
986 name_tables = (LttvNameTables *)*(v.v_pointer);
eed2ef37 987 //tcs->eventtype_names = name_tables->eventtype_names;
f95bc830 988 tcs->syscall_names = name_tables->syscall_names;
7cd289b0 989 tcs->nb_syscalls = name_tables->nb_syscalls;
f95bc830 990 tcs->trap_names = name_tables->trap_names;
991 tcs->irq_names = name_tables->irq_names;
faf074a3 992 tcs->soft_irq_names = name_tables->soft_irq_names;
f95bc830 993}
994
995
b445142a 996static void
997free_name_tables(LttvTraceState *tcs)
998{
f95bc830 999 LttvNameTables *name_tables;
1000
1001 LttvAttributeValue v;
1002
1003 lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_NAME_TABLES,
1004 LTTV_POINTER, &v);
1005 name_tables = (LttvNameTables *)*(v.v_pointer);
1006 *(v.v_pointer) = NULL;
1007
eed2ef37 1008 // g_free(name_tables->eventtype_names);
285468d4 1009 if(name_tables->syscall_names) g_free(name_tables->syscall_names);
1010 if(name_tables->trap_names) g_free(name_tables->trap_names);
1011 if(name_tables->irq_names) g_free(name_tables->irq_names);
1012 if(name_tables->soft_irq_names) g_free(name_tables->soft_irq_names);
1013 if(name_tables) g_free(name_tables);
b445142a 1014}
dc877563 1015
15b3d537 1016#ifdef HASH_TABLE_DEBUG
1017
1018static void test_process(gpointer key, gpointer value, gpointer user_data)
1019{
1020 LttvProcessState *process = (LttvProcessState *)value;
1021
1022 /* Test for process corruption */
1023 guint stack_len = process->execution_stack->len;
1024}
1025
1026static void hash_table_check(GHashTable *table)
1027{
1028 g_hash_table_foreach(table, test_process, NULL);
1029}
1030
1031
1032#endif
1033
1034
b445142a 1035static void push_state(LttvTracefileState *tfs, LttvExecutionMode t,
ffd54a90 1036 guint state_id)
dc877563 1037{
b445142a 1038 LttvExecutionState *es;
348c6ba8 1039
348c6ba8 1040 LttvTraceState *ts = (LttvTraceState*)tfs->parent.t_context;
ae3d0f50 1041 guint cpu = tfs->cpu;
15b3d537 1042
1043#ifdef HASH_TABLE_DEBUG
1044 hash_table_check(ts->processes);
1045#endif
348c6ba8 1046 LttvProcessState *process = ts->running_process[cpu];
dc877563 1047
b445142a 1048 guint depth = process->execution_stack->len;
dc877563 1049
e05fc742 1050 process->execution_stack =
1051 g_array_set_size(process->execution_stack, depth + 1);
1052 /* Keep in sync */
1053 process->state =
1054 &g_array_index(process->execution_stack, LttvExecutionState, depth - 1);
1055
b445142a 1056 es = &g_array_index(process->execution_stack, LttvExecutionState, depth);
1057 es->t = t;
1058 es->n = state_id;
1059 es->entry = es->change = tfs->parent.timestamp;
b49e54b4 1060 es->cum_cpu_time = ltt_time_zero;
b445142a 1061 es->s = process->state->s;
1062 process->state = es;
dc877563 1063}
1064
b49e54b4 1065/* pop state
1066 * return 1 when empty, else 0 */
1067int lttv_state_pop_state_cleanup(LttvProcessState *process,
1068 LttvTracefileState *tfs)
1069{
1070 guint cpu = tfs->cpu;
1071 LttvTraceState *ts = (LttvTraceState*)tfs->parent.t_context;
1072
1073 guint depth = process->execution_stack->len;
1074
1075 if(depth == 1){
1076 return 1;
1077 }
1078
1079 process->execution_stack =
1080 g_array_set_size(process->execution_stack, depth - 1);
1081 process->state = &g_array_index(process->execution_stack, LttvExecutionState,
1082 depth - 2);
1083 process->state->change = tfs->parent.timestamp;
1084
1085 return 0;
1086}
dc877563 1087
b445142a 1088static void pop_state(LttvTracefileState *tfs, LttvExecutionMode t)
dc877563 1089{
ae3d0f50 1090 guint cpu = tfs->cpu;
348c6ba8 1091 LttvTraceState *ts = (LttvTraceState*)tfs->parent.t_context;
1092 LttvProcessState *process = ts->running_process[cpu];
dc877563 1093
f95bc830 1094 guint depth = process->execution_stack->len;
dc877563 1095
3d27549e 1096 if(process->state->t != t){
00e74b69 1097 g_info("Different execution mode type (%lu.%09lu): ignore it\n",
b445142a 1098 tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec);
08b1c66e 1099 g_info("process state has %s when pop_int is %s\n",
8e8e6b64 1100 g_quark_to_string(process->state->t),
1101 g_quark_to_string(t));
08b1c66e 1102 g_info("{ %u, %u, %s, %s }\n",
8e8e6b64 1103 process->pid,
1104 process->ppid,
1105 g_quark_to_string(process->name),
1106 g_quark_to_string(process->state->s));
3d27549e 1107 return;
1108 }
b445142a 1109
f95bc830 1110 if(depth == 1){
00e74b69 1111 g_info("Trying to pop last state on stack (%lu.%09lu): ignore it\n",
b445142a 1112 tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec);
1113 return;
1114 }
1115
e05fc742 1116 process->execution_stack =
1117 g_array_set_size(process->execution_stack, depth - 1);
b445142a 1118 process->state = &g_array_index(process->execution_stack, LttvExecutionState,
f95bc830 1119 depth - 2);
b445142a 1120 process->state->change = tfs->parent.timestamp;
dc877563 1121}
1122
6806b3c6 1123struct search_result {
1124 const LttTime *time; /* Requested time */
1125 LttTime *best; /* Best result */
1126};
1127
1128static gint search_usertrace(gconstpointer a, gconstpointer b)
1129{
1130 const LttTime *elem_time = (const LttTime*)a;
1131 /* Explicit non const cast */
1132 struct search_result *res = (struct search_result *)b;
1133
1134 if(ltt_time_compare(*elem_time, *(res->time)) < 0) {
1135 /* The usertrace was created before the schedchange */
1136 /* Get larger keys */
1137 return 1;
1138 } else if(ltt_time_compare(*elem_time, *(res->time)) >= 0) {
1139 /* The usertrace was created after the schedchange time */
1140 /* Get smaller keys */
1141 if(res->best) {
1142 if(ltt_time_compare(*elem_time, *res->best) < 0) {
1143 res->best = elem_time;
1144 }
1145 } else {
1146 res->best = elem_time;
1147 }
1148 return -1;
1149 }
14236daa 1150 return 0;
6806b3c6 1151}
1152
1153static LttvTracefileState *ltt_state_usertrace_find(LttvTraceState *tcs,
1154 guint pid, const LttTime *timestamp)
1155{
1156 LttvTracefileState *tfs = NULL;
1157 struct search_result res;
1158 /* Find the usertrace associated with a pid and time interval.
1159 * Search in the usertraces by PID (within a hash) and then, for each
1160 * corresponding element of the array, find the first one with creation
1161 * timestamp the lowest, but higher or equal to "timestamp". */
1162 res.time = timestamp;
1163 res.best = NULL;
1164 GTree *usertrace_tree = g_hash_table_lookup(tcs->usertraces, (gpointer)pid);
1165 if(usertrace_tree) {
1166 g_tree_search(usertrace_tree, search_usertrace, &res);
1167 if(res.best)
1168 tfs = g_tree_lookup(usertrace_tree, res.best);
1169 }
1170
1171 return tfs;
1172}
1173
dc877563 1174
2a2fa4f0 1175LttvProcessState *
348c6ba8 1176lttv_state_create_process(LttvTraceState *tcs, LttvProcessState *parent,
b3fd4c02 1177 guint cpu, guint pid, GQuark name, const LttTime *timestamp)
dc877563 1178{
1179 LttvProcessState *process = g_new(LttvProcessState, 1);
1180
b445142a 1181 LttvExecutionState *es;
dc877563 1182
348c6ba8 1183 LttvTraceContext *tc = (LttvTraceContext*)tcs;
ba576a78 1184
b445142a 1185 char buffer[128];
ffd54a90 1186
dc877563 1187 process->pid = pid;
348c6ba8 1188 process->cpu = cpu;
b3fd4c02 1189 process->name = name;
348c6ba8 1190 //process->last_cpu = tfs->cpu_name;
1191 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
e62e7f3a 1192 process->type = LTTV_STATE_USER_THREAD;
6806b3c6 1193 process->usertrace = ltt_state_usertrace_find(tcs, pid, timestamp);
302efbad 1194 process->current_function = 0; //function 0x0 by default.
7bfd7820 1195
cb03932a 1196 g_info("Process %u, core %p", process->pid, process);
2a2fa4f0 1197 g_hash_table_insert(tcs->processes, process, process);
b445142a 1198
1199 if(parent) {
1200 process->ppid = parent->pid;
348c6ba8 1201 process->creation_time = *timestamp;
b445142a 1202 }
2a2fa4f0 1203
1204 /* No parent. This process exists but we are missing all information about
1205 its creation. The birth time is set to zero but we remember the time of
1206 insertion */
1207
b445142a 1208 else {
1209 process->ppid = 0;
2a2fa4f0 1210 process->creation_time = ltt_time_zero;
b445142a 1211 }
1212
348c6ba8 1213 process->insertion_time = *timestamp;
b445142a 1214 sprintf(buffer,"%d-%lu.%lu",pid, process->creation_time.tv_sec,
1215 process->creation_time.tv_nsec);
1216 process->pid_time = g_quark_from_string(buffer);
348c6ba8 1217 process->cpu = cpu;
1218 //process->last_cpu = tfs->cpu_name;
1219 //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
e8f2280c 1220 process->execution_stack = g_array_sized_new(FALSE, FALSE,
1221 sizeof(LttvExecutionState), PREALLOCATED_EXECUTION_STACK);
c607371b 1222 process->execution_stack = g_array_set_size(process->execution_stack, 2);
b445142a 1223 es = process->state = &g_array_index(process->execution_stack,
1224 LttvExecutionState, 0);
1225 es->t = LTTV_STATE_USER_MODE;
1226 es->n = LTTV_STATE_SUBMODE_NONE;
348c6ba8 1227 es->entry = *timestamp;
1228 //g_assert(timestamp->tv_sec != 0);
1229 es->change = *timestamp;
b49e54b4 1230 es->cum_cpu_time = ltt_time_zero;
c607371b 1231 es->s = LTTV_STATE_RUN;
1232
1233 es = process->state = &g_array_index(process->execution_stack,
1234 LttvExecutionState, 1);
1235 es->t = LTTV_STATE_SYSCALL;
1236 es->n = LTTV_STATE_SUBMODE_NONE;
1237 es->entry = *timestamp;
1238 //g_assert(timestamp->tv_sec != 0);
1239 es->change = *timestamp;
b49e54b4 1240 es->cum_cpu_time = ltt_time_zero;
b445142a 1241 es->s = LTTV_STATE_WAIT_FORK;
302efbad 1242
1243 /* Allocate an empty function call stack. If it's empty, use 0x0. */
1244 process->user_stack = g_array_sized_new(FALSE, FALSE,
1245 sizeof(guint64), 0);
1246
cbe7c836 1247 return process;
dc877563 1248}
1249
348c6ba8 1250LttvProcessState *lttv_state_find_process(LttvTraceState *ts, guint cpu,
41c7f803 1251 guint pid)
dc877563 1252{
2a2fa4f0 1253 LttvProcessState key;
1254 LttvProcessState *process;
1255
1256 key.pid = pid;
348c6ba8 1257 key.cpu = cpu;
2a2fa4f0 1258 process = g_hash_table_lookup(ts->processes, &key);
dc877563 1259 return process;
1260}
1261
2a2fa4f0 1262LttvProcessState *
348c6ba8 1263lttv_state_find_process_or_create(LttvTraceState *ts, guint cpu, guint pid,
1264 LttTime *timestamp)
2a2fa4f0 1265{
348c6ba8 1266 LttvProcessState *process = lttv_state_find_process(ts, cpu, pid);
7bfd7820 1267 LttvExecutionState *es;
348c6ba8 1268
1269 /* Put ltt_time_zero creation time for unexisting processes */
7bfd7820 1270 if(unlikely(process == NULL)) {
1271 process = lttv_state_create_process(ts,
b3fd4c02 1272 NULL, cpu, pid, LTTV_STATE_UNNAMED, timestamp);
7bfd7820 1273 /* We are not sure is it's a kernel thread or normal thread, put the
1274 * bottom stack state to unknown */
1275 es = &g_array_index(process->execution_stack, LttvExecutionState, 0);
1276 es->t = LTTV_STATE_MODE_UNKNOWN;
1277 }
2a2fa4f0 1278 return process;
1279}
1280
41c7f803 1281/* FIXME : this function should be called when we receive an event telling that
1282 * release_task has been called in the kernel. In happens generally when
1283 * the parent waits for its child terminaison, but may also happen in special
1284 * cases in the child's exit : when the parent ignores its children SIGCCHLD or
1285 * has the flag SA_NOCLDWAIT. It can also happen when the child is part
1286 * of a killed thread ground, but isn't the leader.
41c7f803 1287 */
b445142a 1288static void exit_process(LttvTracefileState *tfs, LttvProcessState *process)
dc877563 1289{
ba576a78 1290 LttvTraceState *ts = LTTV_TRACE_STATE(tfs->parent.t_context);
2a2fa4f0 1291 LttvProcessState key;
ba576a78 1292
2a2fa4f0 1293 key.pid = process->pid;
348c6ba8 1294 key.cpu = process->cpu;
2a2fa4f0 1295 g_hash_table_remove(ts->processes, &key);
b445142a 1296 g_array_free(process->execution_stack, TRUE);
302efbad 1297 g_array_free(process->user_stack, TRUE);
dc877563 1298 g_free(process);
1299}
1300
1301
b445142a 1302static void free_process_state(gpointer key, gpointer value,gpointer user_data)
dc877563 1303{
b445142a 1304 g_array_free(((LttvProcessState *)value)->execution_stack, TRUE);
302efbad 1305 g_array_free(((LttvProcessState *)value)->user_stack, TRUE);
dc877563 1306 g_free(value);
1307}
1308
1309
308711e5 1310static void lttv_state_free_process_table(GHashTable *processes)
dc877563 1311{
1312 g_hash_table_foreach(processes, free_process_state, NULL);
308711e5 1313 g_hash_table_destroy(processes);
dc877563 1314}
1315
1316
b445142a 1317static gboolean syscall_entry(void *hook_data, void *call_data)
dc877563 1318{
ba576a78 1319 LttvTracefileState *s = (LttvTracefileState *)call_data;
eed2ef37 1320 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
d052ffc3 1321 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
eed2ef37 1322 LttField *f = thf->f1;
dc877563 1323
b445142a 1324 LttvExecutionSubmode submode;
1325
7cd289b0 1326 guint nb_syscalls = ((LttvTraceState *)(s->parent.t_context))->nb_syscalls;
1327 guint syscall = ltt_event_get_unsigned(e, f);
1328
1329 if(syscall < nb_syscalls) {
1330 submode = ((LttvTraceState *)(s->parent.t_context))->syscall_names[
1331 syscall];
1332 } else {
1333 /* Fixup an incomplete syscall table */
1334 GString *string = g_string_new("");
1335 g_string_printf(string, "syscall %u", syscall);
1336 submode = g_quark_from_string(string->str);
1337 g_string_free(string, TRUE);
1338 }
b445142a 1339 push_state(s, LTTV_STATE_SYSCALL, submode);
dc877563 1340 return FALSE;
1341}
1342
1343
b445142a 1344static gboolean syscall_exit(void *hook_data, void *call_data)
dc877563 1345{
ba576a78 1346 LttvTracefileState *s = (LttvTracefileState *)call_data;
dc877563 1347
ffd54a90 1348 pop_state(s, LTTV_STATE_SYSCALL);
dc877563 1349 return FALSE;
1350}
1351
1352
b445142a 1353static gboolean trap_entry(void *hook_data, void *call_data)
dc877563 1354{
ba576a78 1355 LttvTracefileState *s = (LttvTracefileState *)call_data;
eed2ef37 1356 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
d052ffc3 1357 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
eed2ef37 1358 LttField *f = thf->f1;
dc877563 1359
b445142a 1360 LttvExecutionSubmode submode;
1361
1362 submode = ((LttvTraceState *)(s->parent.t_context))->trap_names[
eed2ef37 1363 ltt_event_get_unsigned(e, f)];
b445142a 1364 push_state(s, LTTV_STATE_TRAP, submode);
dc877563 1365 return FALSE;
1366}
1367
1368
b445142a 1369static gboolean trap_exit(void *hook_data, void *call_data)
dc877563 1370{
ba576a78 1371 LttvTracefileState *s = (LttvTracefileState *)call_data;
dc877563 1372
ffd54a90 1373 pop_state(s, LTTV_STATE_TRAP);
dc877563 1374 return FALSE;
1375}
1376
1377
b445142a 1378static gboolean irq_entry(void *hook_data, void *call_data)
dc877563 1379{
ba576a78 1380 LttvTracefileState *s = (LttvTracefileState *)call_data;
eed2ef37 1381 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
9d239bd9 1382 guint8 fac_id = ltt_event_facility_id(e);
1383 guint8 ev_id = ltt_event_eventtype_id(e);
d052ffc3 1384 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
9d239bd9 1385 // g_assert(lttv_trace_hook_get_first((LttvTraceHook *)hook_data)->f1 != NULL);
1386 g_assert(thf->f1 != NULL);
1387 // g_assert(thf == lttv_trace_hook_get_first((LttvTraceHook *)hook_data));
eed2ef37 1388 LttField *f = thf->f1;
dc877563 1389
b445142a 1390 LttvExecutionSubmode submode;
1391
1392 submode = ((LttvTraceState *)(s->parent.t_context))->irq_names[
eed2ef37 1393 ltt_event_get_unsigned(e, f)];
b445142a 1394
dc877563 1395 /* Do something with the info about being in user or system mode when int? */
b445142a 1396 push_state(s, LTTV_STATE_IRQ, submode);
dc877563 1397 return FALSE;
1398}
1399
302efbad 1400static gboolean soft_irq_exit(void *hook_data, void *call_data)
1401{
1402 LttvTracefileState *s = (LttvTracefileState *)call_data;
1403
1404 pop_state(s, LTTV_STATE_SOFT_IRQ);
1405 return FALSE;
1406}
1407
1408
dc877563 1409
b445142a 1410static gboolean irq_exit(void *hook_data, void *call_data)
dc877563 1411{
ba576a78 1412 LttvTracefileState *s = (LttvTracefileState *)call_data;
dc877563 1413
ffd54a90 1414 pop_state(s, LTTV_STATE_IRQ);
dc877563 1415 return FALSE;
1416}
1417
faf074a3 1418static gboolean soft_irq_entry(void *hook_data, void *call_data)
1419{
1420 LttvTracefileState *s = (LttvTracefileState *)call_data;
1421 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
1422 guint8 fac_id = ltt_event_facility_id(e);
1423 guint8 ev_id = ltt_event_eventtype_id(e);
1424 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
1425 // g_assert(lttv_trace_hook_get_first((LttvTraceHook *)hook_data)->f1 != NULL);
1426 g_assert(thf->f1 != NULL);
1427 // g_assert(thf == lttv_trace_hook_get_first((LttvTraceHook *)hook_data));
1428 LttField *f = thf->f1;
1429
1430 LttvExecutionSubmode submode;
1431
1432 submode = ((LttvTraceState *)(s->parent.t_context))->soft_irq_names[
1433 ltt_event_get_unsigned(e, f)];
1434
1435 /* Do something with the info about being in user or system mode when int? */
1436 push_state(s, LTTV_STATE_SOFT_IRQ, submode);
1437 return FALSE;
1438}
1439
302efbad 1440static void push_function(LttvTracefileState *tfs, guint64 funcptr)
1441{
1442 guint64 *new_func;
1443
1444 LttvTraceState *ts = (LttvTraceState*)tfs->parent.t_context;
1445 guint cpu = tfs->cpu;
1446 LttvProcessState *process = ts->running_process[cpu];
faf074a3 1447
302efbad 1448 guint depth = process->user_stack->len;
1449
1450 process->user_stack =
1451 g_array_set_size(process->user_stack, depth + 1);
1452
1453 new_func = &g_array_index(process->user_stack, guint64, depth);
1454 *new_func = funcptr;
9bff13df 1455 process->current_function = funcptr;
302efbad 1456}
1457
1458static void pop_function(LttvTracefileState *tfs, guint64 funcptr)
1459{
1460 guint cpu = tfs->cpu;
1461 LttvTraceState *ts = (LttvTraceState*)tfs->parent.t_context;
1462 LttvProcessState *process = ts->running_process[cpu];
1463
302efbad 1464 if(process->current_function != funcptr){
1465 g_info("Different functions (%lu.%09lu): ignore it\n",
1466 tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec);
1467 g_info("process state has %llu when pop_function is %llu\n",
1468 process->current_function, funcptr);
1469 g_info("{ %u, %u, %s, %s }\n",
1470 process->pid,
1471 process->ppid,
1472 g_quark_to_string(process->name),
1473 g_quark_to_string(process->state->s));
1474 return;
1475 }
9bff13df 1476 guint depth = process->user_stack->len;
302efbad 1477
1478 if(depth == 0){
1479 g_info("Trying to pop last function on stack (%lu.%09lu): ignore it\n",
1480 tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec);
1481 return;
1482 }
1483
1484 process->user_stack =
1485 g_array_set_size(process->user_stack, depth - 1);
1486 process->current_function =
1487 g_array_index(process->user_stack, guint64, depth - 2);
1488}
1489
1490
1491static gboolean function_entry(void *hook_data, void *call_data)
faf074a3 1492{
1493 LttvTracefileState *s = (LttvTracefileState *)call_data;
302efbad 1494 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
1495 guint8 fac_id = ltt_event_facility_id(e);
1496 guint8 ev_id = ltt_event_eventtype_id(e);
1497 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
1498 g_assert(thf->f1 != NULL);
1499 LttField *f = thf->f1;
1500 guint64 funcptr = ltt_event_get_long_unsigned(e, f);
faf074a3 1501
302efbad 1502 push_function(s, funcptr);
faf074a3 1503 return FALSE;
1504}
1505
302efbad 1506static gboolean function_exit(void *hook_data, void *call_data)
1507{
1508 LttvTracefileState *s = (LttvTracefileState *)call_data;
1509 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
1510 guint8 fac_id = ltt_event_facility_id(e);
1511 guint8 ev_id = ltt_event_eventtype_id(e);
1512 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
1513 g_assert(thf->f1 != NULL);
1514 LttField *f = thf->f1;
1515 guint64 funcptr = ltt_event_get_long_unsigned(e, f);
1516
1517 LttvExecutionSubmode submode;
1518
1519 pop_function(s, funcptr);
1520 return FALSE;
1521}
dc877563 1522
b445142a 1523static gboolean schedchange(void *hook_data, void *call_data)
dc877563 1524{
ba576a78 1525 LttvTracefileState *s = (LttvTracefileState *)call_data;
ae3d0f50 1526 guint cpu = s->cpu;
348c6ba8 1527 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
1528 LttvProcessState *process = ts->running_process[cpu];
48b002b8 1529 LttvProcessState *old_process = ts->running_process[cpu];
348c6ba8 1530
eed2ef37 1531 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
d052ffc3 1532 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
73394fd3 1533 guint pid_in, pid_out;
1534 gint state_out;
dc877563 1535
eed2ef37 1536 pid_out = ltt_event_get_unsigned(e, thf->f1);
1537 pid_in = ltt_event_get_unsigned(e, thf->f2);
73394fd3 1538 state_out = ltt_event_get_int(e, thf->f3);
348c6ba8 1539
1540 if(likely(process != NULL)) {
b445142a 1541
f95bc830 1542 /* We could not know but it was not the idle process executing.
1543 This should only happen at the beginning, before the first schedule
1544 event, and when the initial information (current process for each CPU)
1545 is missing. It is not obvious how we could, after the fact, compensate
1546 the wrongly attributed statistics. */
1547
240f1fea 1548 //This test only makes sense once the state is known and if there is no
48b002b8 1549 //missing events. We need to silently ignore schedchange coming after a
1550 //process_free, or it causes glitches. (FIXME)
348c6ba8 1551 //if(unlikely(process->pid != pid_out)) {
1552 // g_assert(process->pid == 0);
240f1fea 1553 //}
f95bc830 1554
348c6ba8 1555 if(unlikely(process->state->s == LTTV_STATE_EXIT)) {
1556 process->state->s = LTTV_STATE_ZOMBIE;
791dffa6 1557 process->state->change = s->parent.timestamp;
dbd243b1 1558 } else {
348c6ba8 1559 if(unlikely(state_out == 0)) process->state->s = LTTV_STATE_WAIT_CPU;
1560 else process->state->s = LTTV_STATE_WAIT;
791dffa6 1561 process->state->change = s->parent.timestamp;
1562 }
48b002b8 1563
1564 if(state_out == 32)
791dffa6 1565 exit_process(s, process); /* EXIT_DEAD */
1566 /* see sched.h for states */
dc877563 1567 }
348c6ba8 1568 process = ts->running_process[cpu] =
1569 lttv_state_find_process_or_create(
1570 (LttvTraceState*)s->parent.t_context,
1571 cpu, pid_in,
1572 &s->parent.timestamp);
1573 process->state->s = LTTV_STATE_RUN;
1574 process->cpu = cpu;
ae3d0f50 1575 if(process->usertrace)
1576 process->usertrace->cpu = cpu;
348c6ba8 1577 // process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)s)->tf);
1578 process->state->change = s->parent.timestamp;
dc877563 1579 return FALSE;
1580}
1581
eed2ef37 1582static gboolean process_fork(void *hook_data, void *call_data)
dc877563 1583{
eed2ef37 1584 LttvTracefileState *s = (LttvTracefileState *)call_data;
1585 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
d052ffc3 1586 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
eed2ef37 1587 guint parent_pid;
2cdc690b 1588 guint child_pid;
4ad73431 1589 LttvProcessState *zombie_process;
ae3d0f50 1590 guint cpu = s->cpu;
348c6ba8 1591 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
1592 LttvProcessState *process = ts->running_process[cpu];
26275aa2 1593 LttvProcessState *child_process;
2cdc690b 1594
eed2ef37 1595 /* Parent PID */
b3fd4c02 1596 parent_pid = ltt_event_get_unsigned(e, thf->f1);
eed2ef37 1597
2cdc690b 1598 /* Child PID */
b3fd4c02 1599 child_pid = ltt_event_get_unsigned(e, thf->f2);
2cdc690b 1600
15b3d537 1601 /* Mathieu : it seems like the process might have been scheduled in before the
1602 * fork, and, in a rare case, might be the current process. This might happen
d4942a23 1603 * in a SMP case where we don't have enough precision on the clocks.
1604 *
1605 * Test reenabled after precision fixes on time. (Mathieu) */
791dffa6 1606#if 0
348c6ba8 1607 zombie_process = lttv_state_find_process(ts, ANY_CPU, child_pid);
dc877563 1608
1d1df11d 1609 if(unlikely(zombie_process != NULL)) {
4ad73431 1610 /* Reutilisation of PID. Only now we are sure that the old PID
eed2ef37 1611 * has been released. FIXME : should know when release_task happens instead.
4ad73431 1612 */
15b3d537 1613 guint num_cpus = ltt_trace_get_num_cpu(ts->parent.t);
1614 guint i;
1615 for(i=0; i< num_cpus; i++) {
5ac05980 1616 g_assert(zombie_process != ts->running_process[i]);
15b3d537 1617 }
1618
4ad73431 1619 exit_process(s, zombie_process);
1620 }
791dffa6 1621#endif //0
348c6ba8 1622 g_assert(process->pid != child_pid);
eed2ef37 1623 // FIXME : Add this test in the "known state" section
348c6ba8 1624 // g_assert(process->pid == parent_pid);
26275aa2 1625 child_process = lttv_state_find_process(ts, ANY_CPU, child_pid);
1626 if(child_process == NULL) {
ab893fb1 1627 child_process = lttv_state_create_process(ts, process, cpu,
b3fd4c02 1628 child_pid, LTTV_STATE_UNNAMED, &s->parent.timestamp);
26275aa2 1629 } else {
1630 /* The process has already been created : due to time imprecision between
791dffa6 1631 * multiple CPUs : it has been scheduled in before creation. Note that we
1632 * shouldn't have this kind of imprecision.
26275aa2 1633 *
1634 * Simply put a correct parent.
1635 */
6806b3c6 1636 g_assert(0); /* This is a problematic case : the process has been created
1637 before the fork event */
26275aa2 1638 child_process->ppid = process->pid;
1639 }
ab893fb1 1640 g_assert(child_process->name == LTTV_STATE_UNNAMED);
1641 child_process->name = process->name;
4ad73431 1642
dc877563 1643 return FALSE;
1644}
1645
7bfd7820 1646/* We stamp a newly created process as kernel_thread */
1647static gboolean process_kernel_thread(void *hook_data, void *call_data)
1648{
1649 LttvTracefileState *s = (LttvTracefileState *)call_data;
1650 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
1651 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
1652 guint pid;
ae3d0f50 1653 guint cpu = s->cpu;
7bfd7820 1654 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
1655 LttvProcessState *process;
1656 LttvExecutionState *es;
1657
1658 /* PID */
1659 pid = ltt_event_get_unsigned(e, thf->f1);
1660
1661 process = lttv_state_find_process(ts, ANY_CPU, pid);
1662 es = &g_array_index(process->execution_stack, LttvExecutionState, 0);
1663 es->t = LTTV_STATE_SYSCALL;
e62e7f3a 1664 process->type = LTTV_STATE_KERNEL_THREAD;
7bfd7820 1665
1666 return FALSE;
1667}
dc877563 1668
eed2ef37 1669static gboolean process_exit(void *hook_data, void *call_data)
dc877563 1670{
eed2ef37 1671 LttvTracefileState *s = (LttvTracefileState *)call_data;
1672 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
d052ffc3 1673 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
eed2ef37 1674 LttField *f;
1675 guint pid;
ae3d0f50 1676 guint cpu = s->cpu;
348c6ba8 1677 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
1678 LttvProcessState *process = ts->running_process[cpu];
eed2ef37 1679
1680 pid = ltt_event_get_unsigned(e, thf->f1);
1681
1682 // FIXME : Add this test in the "known state" section
348c6ba8 1683 // g_assert(process->pid == pid);
eed2ef37 1684
348c6ba8 1685 if(likely(process != NULL)) {
1686 process->state->s = LTTV_STATE_EXIT;
2cdc690b 1687 }
1688 return FALSE;
2cdc690b 1689}
1690
eed2ef37 1691static gboolean process_free(void *hook_data, void *call_data)
2da61677 1692{
eed2ef37 1693 LttvTracefileState *s = (LttvTracefileState *)call_data;
348c6ba8 1694 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
eed2ef37 1695 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
d052ffc3 1696 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
2da61677 1697 guint release_pid;
1698 LttvProcessState *process;
1699
1700 /* PID of the process to release */
eed2ef37 1701 release_pid = ltt_event_get_unsigned(e, thf->f1);
15b3d537 1702
1703 g_assert(release_pid != 0);
2da61677 1704
348c6ba8 1705 process = lttv_state_find_process(ts, ANY_CPU, release_pid);
2da61677 1706
1707 if(likely(process != NULL)) {
1708 /* release_task is happening at kernel level : we can now safely release
1709 * the data structure of the process */
5562ddce 1710 //This test is fun, though, as it may happen that
1711 //at time t : CPU 0 : process_free
1712 //at time t+150ns : CPU 1 : schedule out
1713 //Clearly due to time imprecision, we disable it. (Mathieu)
1714 //If this weird case happen, we have no choice but to put the
1715 //Currently running process on the cpu to 0.
791dffa6 1716 //I re-enable it following time precision fixes. (Mathieu)
1717 //Well, in the case where an process is freed by a process on another CPU
1718 //and still scheduled, it happens that this is the schedchange that will
1719 //drop the last reference count. Do not free it here!
0bd2f89c 1720 guint num_cpus = ltt_trace_get_num_cpu(ts->parent.t);
1721 guint i;
1722 for(i=0; i< num_cpus; i++) {
5562ddce 1723 //g_assert(process != ts->running_process[i]);
1724 if(process == ts->running_process[i]) {
791dffa6 1725 //ts->running_process[i] = lttv_state_find_process(ts, i, 0);
1726 break;
5562ddce 1727 }
0bd2f89c 1728 }
48b002b8 1729 //if(i == num_cpus) /* process is not scheduled */
1730 //exit_process(s, process); // do nothing : wait for the schedchange to
1731 //delete the process.
2da61677 1732 }
1733
1734 return FALSE;
1735}
1736
f4b88a7d 1737
1738static gboolean process_exec(void *hook_data, void *call_data)
1739{
1740 LttvTracefileState *s = (LttvTracefileState *)call_data;
1741 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
1742 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
1743 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
743e50fd 1744 //gchar *name;
ae3d0f50 1745 guint cpu = s->cpu;
f4b88a7d 1746 LttvProcessState *process = ts->running_process[cpu];
1747
1748 /* PID of the process to release */
743e50fd 1749 guint64 name_len = ltt_event_field_element_number(e, thf->f1);
1750 //name = ltt_event_get_string(e, thf->f1);
f2923fb2 1751 LttField *child = ltt_event_field_element_select(e, thf->f1, 0);
1752 gchar *name_begin =
1753 (gchar*)(ltt_event_data(e)+ltt_event_field_offset(e, child));
743e50fd 1754 gchar *null_term_name = g_new(gchar, name_len+1);
1755 memcpy(null_term_name, name_begin, name_len);
1756 null_term_name[name_len] = '\0';
1757
1758 process->name = g_quark_from_string(null_term_name);
f2923fb2 1759 g_free(null_term_name);
f4b88a7d 1760 return FALSE;
1761}
1762
b3fd4c02 1763static gboolean enum_process_state(void *hook_data, void *call_data)
1764{
1765 LttvTracefileState *s = (LttvTracefileState *)call_data;
1766 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
1767 //It's slow : optimise later by doing this before reading trace.
1768 LttEventType *et = ltt_event_eventtype(e);
1769 //
1770 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
1771 guint parent_pid;
1772 guint pid;
1773 gchar * command;
ae3d0f50 1774 guint cpu = s->cpu;
b3fd4c02 1775 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
1776 LttvProcessState *process = ts->running_process[cpu];
1777 LttvProcessState *parent_process;
e62e7f3a 1778 LttField *f4, *f5, *f6, *f7;
1779 GQuark type, mode, submode, status;
1780 LttvExecutionState *es;
f4b88a7d 1781
b3fd4c02 1782 /* PID */
1783 pid = ltt_event_get_unsigned(e, thf->f1);
f4b88a7d 1784
b3fd4c02 1785 /* Parent PID */
1786 parent_pid = ltt_event_get_unsigned(e, thf->f2);
1787
1788 /* Command name */
1789 command = ltt_event_get_string(e, thf->f3);
1790
e62e7f3a 1791 /* type */
1792 f4 = ltt_eventtype_field_by_name(et, LTT_FIELD_TYPE);
1793 type = ltt_enum_string_get(ltt_field_type(f4),
b3fd4c02 1794 ltt_event_get_unsigned(e, f4));
1795
e62e7f3a 1796 /* mode */
1797 f5 = ltt_eventtype_field_by_name(et, LTT_FIELD_MODE);
1798 mode = ltt_enum_string_get(ltt_field_type(f5),
b3fd4c02 1799 ltt_event_get_unsigned(e, f5));
1800
e62e7f3a 1801 /* submode */
1802 f6 = ltt_eventtype_field_by_name(et, LTT_FIELD_SUBMODE);
1803 submode = ltt_enum_string_get(ltt_field_type(f6),
b3fd4c02 1804 ltt_event_get_unsigned(e, f6));
1805
e62e7f3a 1806 /* status */
1807 f7 = ltt_eventtype_field_by_name(et, LTT_FIELD_STATUS);
1808 status = ltt_enum_string_get(ltt_field_type(f7),
1809 ltt_event_get_unsigned(e, f7));
1810
b3fd4c02 1811 /* The process might exist if a process was forked while performing the sate dump. */
1812 process = lttv_state_find_process(ts, ANY_CPU, pid);
1813 if(process == NULL) {
1814 parent_process = lttv_state_find_process(ts, ANY_CPU, parent_pid);
1815 process = lttv_state_create_process(ts, parent_process, cpu,
1816 pid, g_quark_from_string(command),
1817 &s->parent.timestamp);
1818
1819 /* Keep the stack bottom : a running user mode */
ab893fb1 1820 /* Disabled because of inconsistencies in the current statedump states. */
e62e7f3a 1821 if(type == LTTV_STATE_KERNEL_THREAD) {
b3fd4c02 1822 /* Only keep the bottom */
1823 process->execution_stack = g_array_set_size(process->execution_stack, 1);
e62e7f3a 1824 es = process->state = &g_array_index(process->execution_stack,
1825 LttvExecutionState, 0);
1826 es->t = LTTV_STATE_SYSCALL;
1827 es->s = status;
1828 es->n = submode;
b3fd4c02 1829 } else {
1830 /* On top of it : */
b3fd4c02 1831 es = process->state = &g_array_index(process->execution_stack,
1832 LttvExecutionState, 1);
e62e7f3a 1833 es->t = LTTV_STATE_USER_MODE;
b3fd4c02 1834 es->s = status;
1835 es->n = submode;
1836 }
e62e7f3a 1837#if 0
ab893fb1 1838 /* UNKNOWN STATE */
1839 {
ab893fb1 1840 es = process->state = &g_array_index(process->execution_stack,
1841 LttvExecutionState, 1);
1842 es->t = LTTV_STATE_MODE_UNKNOWN;
1843 es->s = LTTV_STATE_UNNAMED;
1844 es->n = LTTV_STATE_SUBMODE_UNKNOWN;
1845 }
e62e7f3a 1846#endif //0
b3fd4c02 1847 } else {
1848 /* The process has already been created :
1849 * Probably was forked while dumping the process state or
1850 * was simply scheduled in prior to get the state dump event.
e62e7f3a 1851 * We know for sure if it is a user space thread.
b3fd4c02 1852 */
1853 process->ppid = parent_pid;
1854 process->name = g_quark_from_string(command);
e62e7f3a 1855 es = &g_array_index(process->execution_stack, LttvExecutionState, 0);
1856 if(type != LTTV_STATE_KERNEL_THREAD)
1857 es->t = LTTV_STATE_USER_MODE;
b3fd4c02 1858 /* Don't mess around with the stack, it will eventually become
1859 * ok after the end of state dump. */
1860 }
1861
1862 return FALSE;
1863}
f4b88a7d 1864
58c88a41 1865gint lttv_state_hook_add_event_hooks(void *hook_data, void *call_data)
1866{
1867 LttvTracesetState *tss = (LttvTracesetState*)(call_data);
1868
1869 lttv_state_add_event_hooks(tss);
1870
1871 return 0;
1872}
dc877563 1873
308711e5 1874void lttv_state_add_event_hooks(LttvTracesetState *self)
dc877563 1875{
ba576a78 1876 LttvTraceset *traceset = self->parent.ts;
dc877563 1877
eed2ef37 1878 guint i, j, k, l, nb_trace, nb_tracefile;
dc877563 1879
ba576a78 1880 LttvTraceState *ts;
dc877563 1881
ba576a78 1882 LttvTracefileState *tfs;
dc877563 1883
dc877563 1884 GArray *hooks;
1885
eed2ef37 1886 LttvTraceHookByFacility *thf;
1887
1888 LttvTraceHook *hook;
dc877563 1889
1890 LttvAttributeValue val;
1891
9d239bd9 1892 gint ret;
302efbad 1893 gint hn;
9d239bd9 1894
ba576a78 1895 nb_trace = lttv_traceset_number(traceset);
dc877563 1896 for(i = 0 ; i < nb_trace ; i++) {
ba576a78 1897 ts = (LttvTraceState *)self->parent.traces[i];
dc877563 1898
1899 /* Find the eventtype id for the following events and register the
1900 associated by id hooks. */
1901
302efbad 1902 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 17);
1903 hooks = g_array_set_size(hooks, 17); // Max possible number of hooks.
1904 hn = 0;
b445142a 1905
9d239bd9 1906 ret = lttv_trace_find_hook(ts->parent.t,
f5d7967f 1907 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_ENTRY,
eed2ef37 1908 LTT_FIELD_SYSCALL_ID, 0, 0,
302efbad 1909 syscall_entry, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
1910 if(ret) hn--;
cbe7c836 1911
9d239bd9 1912 ret = lttv_trace_find_hook(ts->parent.t,
f5d7967f 1913 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_EXIT,
eed2ef37 1914 0, 0, 0,
302efbad 1915 syscall_exit, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
1916 if(ret) hn--;
cbe7c836 1917
9d239bd9 1918 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 1919 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY,
1920 LTT_FIELD_TRAP_ID, 0, 0,
302efbad 1921 trap_entry, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
1922 if(ret) hn--;
cbe7c836 1923
9d239bd9 1924 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 1925 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT,
1926 0, 0, 0,
302efbad 1927 trap_exit, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
1928 if(ret) hn--;
cbe7c836 1929
9d239bd9 1930 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 1931 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
1932 LTT_FIELD_IRQ_ID, 0, 0,
302efbad 1933 irq_entry, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
1934 if(ret) hn--;
cbe7c836 1935
9d239bd9 1936 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 1937 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
1938 0, 0, 0,
302efbad 1939 irq_exit, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
1940 if(ret) hn--;
cbe7c836 1941
faf074a3 1942 ret = lttv_trace_find_hook(ts->parent.t,
1943 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_ENTRY,
1944 LTT_FIELD_SOFT_IRQ_ID, 0, 0,
302efbad 1945 soft_irq_entry, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
1946 if(ret) hn--;
faf074a3 1947
1948 ret = lttv_trace_find_hook(ts->parent.t,
1949 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_EXIT,
1950 0, 0, 0,
302efbad 1951 soft_irq_exit, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
1952 if(ret) hn--;
faf074a3 1953
9d239bd9 1954 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 1955 LTT_FACILITY_PROCESS, LTT_EVENT_SCHEDCHANGE,
1956 LTT_FIELD_OUT, LTT_FIELD_IN, LTT_FIELD_OUT_STATE,
302efbad 1957 schedchange, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
1958 if(ret) hn--;
cbe7c836 1959
9d239bd9 1960 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 1961 LTT_FACILITY_PROCESS, LTT_EVENT_FORK,
1962 LTT_FIELD_PARENT_PID, LTT_FIELD_CHILD_PID, 0,
302efbad 1963 process_fork, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
1964 if(ret) hn--;
eed2ef37 1965
7bfd7820 1966 ret = lttv_trace_find_hook(ts->parent.t,
1967 LTT_FACILITY_PROCESS, LTT_EVENT_KERNEL_THREAD,
1968 LTT_FIELD_PID, 0, 0,
302efbad 1969 process_kernel_thread, NULL, &g_array_index(hooks, LttvTraceHook,
1970 hn++));
1971 if(ret) hn--;
7bfd7820 1972
9d239bd9 1973 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 1974 LTT_FACILITY_PROCESS, LTT_EVENT_EXIT,
1975 LTT_FIELD_PID, 0, 0,
302efbad 1976 process_exit, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
1977 if(ret) hn--;
eed2ef37 1978
9d239bd9 1979 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 1980 LTT_FACILITY_PROCESS, LTT_EVENT_FREE,
1981 LTT_FIELD_PID, 0, 0,
302efbad 1982 process_free, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
1983 if(ret) hn--;
2cdc690b 1984
f4b88a7d 1985 ret = lttv_trace_find_hook(ts->parent.t,
1986 LTT_FACILITY_FS, LTT_EVENT_EXEC,
1987 LTT_FIELD_FILENAME, 0, 0,
302efbad 1988 process_exec, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
1989 if(ret) hn--;
f4b88a7d 1990
b3fd4c02 1991 /* statedump-related hooks */
1992 ret = lttv_trace_find_hook(ts->parent.t,
1993 LTT_FACILITY_STATEDUMP, LTT_EVENT_ENUM_PROCESS_STATE,
1994 LTT_FIELD_PID, LTT_FIELD_PARENT_PID, LTT_FIELD_NAME,
302efbad 1995 enum_process_state, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
1996 if(ret) hn--;
f4b88a7d 1997
302efbad 1998 ret = lttv_trace_find_hook(ts->parent.t,
1999 LTT_FACILITY_USER_GENERIC, LTT_EVENT_FUNCTION_ENTRY,
2000 LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE, 0,
2001 function_entry, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
2002 if(ret) hn--;
2003
2004 ret = lttv_trace_find_hook(ts->parent.t,
2005 LTT_FACILITY_USER_GENERIC, LTT_EVENT_FUNCTION_EXIT,
2006 LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE, 0,
2007 function_exit, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
2008 if(ret) hn--;
2009
2010 hooks = g_array_set_size(hooks, hn);
2011
a5ba1787 2012 /* Add these hooks to each event_by_id hooks list */
dc877563 2013
eed2ef37 2014 nb_tracefile = ts->parent.tracefiles->len;
dbb7bb09 2015
dc877563 2016 for(j = 0 ; j < nb_tracefile ; j++) {
eed2ef37 2017 tfs =
9d239bd9 2018 LTTV_TRACEFILE_STATE(g_array_index(ts->parent.tracefiles,
2019 LttvTracefileContext*, j));
dc877563 2020
2021 for(k = 0 ; k < hooks->len ; k++) {
eed2ef37 2022 hook = &g_array_index(hooks, LttvTraceHook, k);
2023 for(l=0;l<hook->fac_list->len;l++) {
2024 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
2025 lttv_hooks_add(
2026 lttv_hooks_by_id_find(tfs->parent.event_by_id, thf->id),
2027 thf->h,
d052ffc3 2028 thf,
eed2ef37 2029 LTTV_PRIO_STATE);
2030 }
ffd54a90 2031 }
dc877563 2032 }
f0b795e0 2033 lttv_attribute_find(ts->parent.a, LTTV_STATE_HOOKS, LTTV_POINTER, &val);
ba576a78 2034 *(val.v_pointer) = hooks;
dc877563 2035 }
2036}
2037
58c88a41 2038gint lttv_state_hook_remove_event_hooks(void *hook_data, void *call_data)
2039{
2040 LttvTracesetState *tss = (LttvTracesetState*)(call_data);
2041
2042 lttv_state_remove_event_hooks(tss);
2043
2044 return 0;
2045}
dc877563 2046
308711e5 2047void lttv_state_remove_event_hooks(LttvTracesetState *self)
dc877563 2048{
ba576a78 2049 LttvTraceset *traceset = self->parent.ts;
dc877563 2050
eed2ef37 2051 guint i, j, k, l, nb_trace, nb_tracefile;
dc877563 2052
ba576a78 2053 LttvTraceState *ts;
dc877563 2054
ba576a78 2055 LttvTracefileState *tfs;
dc877563 2056
dc877563 2057 GArray *hooks;
2058
eed2ef37 2059 LttvTraceHook *hook;
2060
2061 LttvTraceHookByFacility *thf;
dc877563 2062
2063 LttvAttributeValue val;
2064
ba576a78 2065 nb_trace = lttv_traceset_number(traceset);
dc877563 2066 for(i = 0 ; i < nb_trace ; i++) {
021eeb41 2067 ts = LTTV_TRACE_STATE(self->parent.traces[i]);
f0b795e0 2068 lttv_attribute_find(ts->parent.a, LTTV_STATE_HOOKS, LTTV_POINTER, &val);
ba576a78 2069 hooks = *(val.v_pointer);
dc877563 2070
a5ba1787 2071 /* Remove these hooks from each event_by_id hooks list */
dc877563 2072
eed2ef37 2073 nb_tracefile = ts->parent.tracefiles->len;
dbb7bb09 2074
dc877563 2075 for(j = 0 ; j < nb_tracefile ; j++) {
eed2ef37 2076 tfs =
cb03932a 2077 LTTV_TRACEFILE_STATE(g_array_index(ts->parent.tracefiles,
2078 LttvTracefileContext*, j));
dc877563 2079
2080 for(k = 0 ; k < hooks->len ; k++) {
eed2ef37 2081 hook = &g_array_index(hooks, LttvTraceHook, k);
2082 for(l=0;l<hook->fac_list->len;l++) {
2083 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
2084
2085 lttv_hooks_remove_data(
2086 lttv_hooks_by_id_find(tfs->parent.event_by_id, thf->id),
2087 thf->h,
d052ffc3 2088 thf);
eed2ef37 2089 }
ffd54a90 2090 }
dc877563 2091 }
1986f254 2092 for(k = 0 ; k < hooks->len ; k++)
2093 lttv_trace_hook_destroy(&g_array_index(hooks, LttvTraceHook, k));
dc877563 2094 g_array_free(hooks, TRUE);
2095 }
2096}
2097
eed2ef37 2098static gboolean state_save_event_hook(void *hook_data, void *call_data)
2099{
2100 guint *event_count = (guint*)hook_data;
2101
2102 /* Only save at LTTV_STATE_SAVE_INTERVAL */
2103 if(likely((*event_count)++ < LTTV_STATE_SAVE_INTERVAL))
2104 return FALSE;
2105 else
18c87975 2106 *event_count = 0;
eed2ef37 2107
2108 LttvTracefileState *self = (LttvTracefileState *)call_data;
2109
2110 LttvTracefileState *tfcs;
2111
2112 LttvTraceState *tcs = (LttvTraceState *)(self->parent.t_context);
2113
2114 LttEventPosition *ep;
2115
2116 guint i;
2117
2118 LttTracefile *tf;
2119
2120 LttvAttribute *saved_states_tree, *saved_state_tree;
2121
2122 LttvAttributeValue value;
2123
2124 saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a,
2125 LTTV_STATE_SAVED_STATES);
2126 saved_state_tree = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
2127 value = lttv_attribute_add(saved_states_tree,
2128 lttv_attribute_get_number(saved_states_tree), LTTV_GOBJECT);
2129 *(value.v_gobject) = (GObject *)saved_state_tree;
2130 value = lttv_attribute_add(saved_state_tree, LTTV_STATE_TIME, LTTV_TIME);
2131 *(value.v_time) = self->parent.timestamp;
2132 lttv_state_save(tcs, saved_state_tree);
2133 g_debug("Saving state at time %lu.%lu", self->parent.timestamp.tv_sec,
2134 self->parent.timestamp.tv_nsec);
2135
2136 *(tcs->max_time_state_recomputed_in_seek) = self->parent.timestamp;
2137
2138 return FALSE;
2139}
2140
14aecf75 2141static gboolean state_save_after_trace_hook(void *hook_data, void *call_data)
2142{
2143 LttvTraceState *tcs = (LttvTraceState *)(call_data);
2144
2145 *(tcs->max_time_state_recomputed_in_seek) = tcs->parent.time_span.end_time;
2146
2147 return FALSE;
2148}
2149
ae3d0f50 2150guint lttv_state_current_cpu(LttvTracefileState *tfs)
2151{
2152 return tfs->cpu;
2153}
2154
2155
2156
eed2ef37 2157#if 0
08b1c66e 2158static gboolean block_start(void *hook_data, void *call_data)
308711e5 2159{
dbb7bb09 2160 LttvTracefileState *self = (LttvTracefileState *)call_data;
308711e5 2161
dbb7bb09 2162 LttvTracefileState *tfcs;
308711e5 2163
dbb7bb09 2164 LttvTraceState *tcs = (LttvTraceState *)(self->parent.t_context);
2165
2166 LttEventPosition *ep;
308711e5 2167
dbb7bb09 2168 guint i, nb_block, nb_event, nb_tracefile;
308711e5 2169
2170 LttTracefile *tf;
2171
2172 LttvAttribute *saved_states_tree, *saved_state_tree;
2173
2174 LttvAttributeValue value;
2175
dbb7bb09 2176 ep = ltt_event_position_new();
eed2ef37 2177
2178 nb_tracefile = tcs->parent.tracefiles->len;
dbb7bb09 2179
2180 /* Count the number of events added since the last block end in any
2181 tracefile. */
2182
2183 for(i = 0 ; i < nb_tracefile ; i++) {
eed2ef37 2184 tfcs =
2185 LTTV_TRACEFILE_STATE(&g_array_index(tcs->parent.tracefiles,
2186 LttvTracefileContext, i));
dbb7bb09 2187 ltt_event_position(tfcs->parent.e, ep);
2188 ltt_event_position_get(ep, &nb_block, &nb_event, &tf);
2189 tcs->nb_event += nb_event - tfcs->saved_position;
2190 tfcs->saved_position = nb_event;
2191 }
2192 g_free(ep);
308711e5 2193
308711e5 2194 if(tcs->nb_event >= tcs->save_interval) {
2195 saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a,
2196 LTTV_STATE_SAVED_STATES);
2197 saved_state_tree = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
2198 value = lttv_attribute_add(saved_states_tree,
2199 lttv_attribute_get_number(saved_states_tree), LTTV_GOBJECT);
2200 *(value.v_gobject) = (GObject *)saved_state_tree;
2201 value = lttv_attribute_add(saved_state_tree, LTTV_STATE_TIME, LTTV_TIME);
dbb7bb09 2202 *(value.v_time) = self->parent.timestamp;
308711e5 2203 lttv_state_save(tcs, saved_state_tree);
2204 tcs->nb_event = 0;
08b1c66e 2205 g_debug("Saving state at time %lu.%lu", self->parent.timestamp.tv_sec,
2206 self->parent.timestamp.tv_nsec);
308711e5 2207 }
dbb7bb09 2208 *(tcs->max_time_state_recomputed_in_seek) = self->parent.timestamp;
308711e5 2209 return FALSE;
2210}
eed2ef37 2211#endif //0
308711e5 2212
eed2ef37 2213#if 0
08b1c66e 2214static gboolean block_end(void *hook_data, void *call_data)
2215{
2216 LttvTracefileState *self = (LttvTracefileState *)call_data;
2217
2218 LttvTraceState *tcs = (LttvTraceState *)(self->parent.t_context);
2219
2220 LttTracefile *tf;
2221
2222 LttEventPosition *ep;
2223
2224 guint nb_block, nb_event;
2225
2226 ep = ltt_event_position_new();
2227 ltt_event_position(self->parent.e, ep);
2228 ltt_event_position_get(ep, &nb_block, &nb_event, &tf);
2229 tcs->nb_event += nb_event - self->saved_position + 1;
2230 self->saved_position = 0;
2231 *(tcs->max_time_state_recomputed_in_seek) = self->parent.timestamp;
2232 g_free(ep);
00e74b69 2233
2234 return FALSE;
08b1c66e 2235}
eed2ef37 2236#endif //0
2237#if 0
308711e5 2238void lttv_state_save_add_event_hooks(LttvTracesetState *self)
2239{
2240 LttvTraceset *traceset = self->parent.ts;
2241
00e74b69 2242 guint i, j, nb_trace, nb_tracefile;
308711e5 2243
2244 LttvTraceState *ts;
2245
2246 LttvTracefileState *tfs;
2247
08b1c66e 2248 LttvTraceHook hook_start, hook_end;
308711e5 2249
2250 nb_trace = lttv_traceset_number(traceset);
2251 for(i = 0 ; i < nb_trace ; i++) {
2252 ts = (LttvTraceState *)self->parent.traces[i];
eed2ef37 2253
08b1c66e 2254 lttv_trace_find_hook(ts->parent.t, "core","block_start",NULL,
2255 NULL, NULL, block_start, &hook_start);
308711e5 2256 lttv_trace_find_hook(ts->parent.t, "core","block_end",NULL,
08b1c66e 2257 NULL, NULL, block_end, &hook_end);
308711e5 2258
eed2ef37 2259 nb_tracefile = ts->parent.tracefiles->len;
308711e5 2260
dbb7bb09 2261 for(j = 0 ; j < nb_tracefile ; j++) {
eed2ef37 2262 tfs =
2263 LTTV_TRACEFILE_STATE(&g_array_index(ts->parent.tracefiles,
2264 LttvTracefileContext, j));
a5ba1787 2265 lttv_hooks_add(lttv_hooks_by_id_find(tfs->parent.event_by_id,
eed2ef37 2266 hook_start.id), hook_start.h, NULL, LTTV_PRIO_STATE);
a5ba1787 2267 lttv_hooks_add(lttv_hooks_by_id_find(tfs->parent.event_by_id,
eed2ef37 2268 hook_end.id), hook_end.h, NULL, LTTV_PRIO_STATE);
2269 }
2270 }
2271}
2272#endif //0
2273
2274void lttv_state_save_add_event_hooks(LttvTracesetState *self)
2275{
2276 LttvTraceset *traceset = self->parent.ts;
2277
2278 guint i, j, nb_trace, nb_tracefile;
2279
2280 LttvTraceState *ts;
2281
2282 LttvTracefileState *tfs;
2283
2284
2285 nb_trace = lttv_traceset_number(traceset);
2286 for(i = 0 ; i < nb_trace ; i++) {
2287
2288 ts = (LttvTraceState *)self->parent.traces[i];
2289 nb_tracefile = ts->parent.tracefiles->len;
2290
3054461a 2291 guint *event_count = g_new(guint, 1);
2292 *event_count = 0;
2293
eed2ef37 2294 for(j = 0 ; j < nb_tracefile ; j++) {
2295 tfs =
cb03932a 2296 LTTV_TRACEFILE_STATE(g_array_index(ts->parent.tracefiles,
2297 LttvTracefileContext*, j));
eed2ef37 2298 lttv_hooks_add(tfs->parent.event,
2299 state_save_event_hook,
2300 event_count,
2301 LTTV_PRIO_STATE);
2302
308711e5 2303 }
2304 }
14aecf75 2305
2306 lttv_process_traceset_begin(&self->parent,
2307 NULL, NULL, NULL, NULL, NULL);
2308
308711e5 2309}
2310
b56b5fec 2311gint lttv_state_save_hook_add_event_hooks(void *hook_data, void *call_data)
2312{
2313 LttvTracesetState *tss = (LttvTracesetState*)(call_data);
2314
2315 lttv_state_save_add_event_hooks(tss);
2316
2317 return 0;
2318}
2319
308711e5 2320
eed2ef37 2321#if 0
308711e5 2322void lttv_state_save_remove_event_hooks(LttvTracesetState *self)
2323{
2324 LttvTraceset *traceset = self->parent.ts;
2325
00e74b69 2326 guint i, j, nb_trace, nb_tracefile;
308711e5 2327
2328 LttvTraceState *ts;
2329
2330 LttvTracefileState *tfs;
2331
08b1c66e 2332 LttvTraceHook hook_start, hook_end;
308711e5 2333
2334 nb_trace = lttv_traceset_number(traceset);
2335 for(i = 0 ; i < nb_trace ; i++) {
2336 ts = LTTV_TRACE_STATE(self->parent.traces[i]);
eed2ef37 2337
08b1c66e 2338 lttv_trace_find_hook(ts->parent.t, "core","block_start",NULL,
2339 NULL, NULL, block_start, &hook_start);
2340
308711e5 2341 lttv_trace_find_hook(ts->parent.t, "core","block_end",NULL,
08b1c66e 2342 NULL, NULL, block_end, &hook_end);
308711e5 2343
eed2ef37 2344 nb_tracefile = ts->parent.tracefiles->len;
308711e5 2345
dbb7bb09 2346 for(j = 0 ; j < nb_tracefile ; j++) {
eed2ef37 2347 tfs =
2348 LTTV_TRACEFILE_STATE(&g_array_index(ts->parent.tracefiles,
2349 LttvTracefileContext, j));
308711e5 2350 lttv_hooks_remove_data(lttv_hooks_by_id_find(
a5ba1787 2351 tfs->parent.event_by_id, hook_start.id), hook_start.h, NULL);
08b1c66e 2352 lttv_hooks_remove_data(lttv_hooks_by_id_find(
a5ba1787 2353 tfs->parent.event_by_id, hook_end.id), hook_end.h, NULL);
308711e5 2354 }
2355 }
2356}
eed2ef37 2357#endif //0
2358
2359void lttv_state_save_remove_event_hooks(LttvTracesetState *self)
2360{
2361 LttvTraceset *traceset = self->parent.ts;
2362
2363 guint i, j, nb_trace, nb_tracefile;
2364
2365 LttvTraceState *ts;
2366
2367 LttvTracefileState *tfs;
2368
14aecf75 2369 LttvHooks *after_trace = lttv_hooks_new();
2370
2371 lttv_hooks_add(after_trace,
2372 state_save_after_trace_hook,
2373 NULL,
2374 LTTV_PRIO_STATE);
2375
2376
2377 lttv_process_traceset_end(&self->parent,
2378 NULL, after_trace, NULL, NULL, NULL);
eed2ef37 2379
14aecf75 2380 lttv_hooks_destroy(after_trace);
2381
eed2ef37 2382 nb_trace = lttv_traceset_number(traceset);
2383 for(i = 0 ; i < nb_trace ; i++) {
2384
2385 ts = (LttvTraceState *)self->parent.traces[i];
2386 nb_tracefile = ts->parent.tracefiles->len;
2387
22b165e9 2388 guint *event_count = NULL;
eed2ef37 2389
2390 for(j = 0 ; j < nb_tracefile ; j++) {
2391 tfs =
cb03932a 2392 LTTV_TRACEFILE_STATE(g_array_index(ts->parent.tracefiles,
2393 LttvTracefileContext*, j));
eed2ef37 2394 event_count = lttv_hooks_remove(tfs->parent.event,
2395 state_save_event_hook);
eed2ef37 2396 }
22b165e9 2397 if(event_count) g_free(event_count);
eed2ef37 2398 }
2399}
308711e5 2400
b56b5fec 2401gint lttv_state_save_hook_remove_event_hooks(void *hook_data, void *call_data)
2402{
2403 LttvTracesetState *tss = (LttvTracesetState*)(call_data);
2404
2405 lttv_state_save_remove_event_hooks(tss);
2406
2407 return 0;
2408}
308711e5 2409
dd025f91 2410void lttv_state_traceset_seek_time_closest(LttvTracesetState *self, LttTime t)
308711e5 2411{
2412 LttvTraceset *traceset = self->parent.ts;
2413
00e74b69 2414 guint i, nb_trace;
308711e5 2415
2416 int min_pos, mid_pos, max_pos;
2417
728d0c3e 2418 guint call_rest = 0;
2419
308711e5 2420 LttvTraceState *tcs;
2421
2422 LttvAttributeValue value;
2423
2424 LttvAttributeType type;
2425
2426 LttvAttributeName name;
2427
c0cb4d12 2428 gboolean is_named;
2429
308711e5 2430 LttvAttribute *saved_states_tree, *saved_state_tree, *closest_tree;
2431
d448fce2 2432 //g_tree_destroy(self->parent.pqueue);
2433 //self->parent.pqueue = g_tree_new(compare_tracefile);
348c6ba8 2434
728d0c3e 2435 g_info("Entering seek_time_closest for time %lu.%lu", t.tv_sec, t.tv_nsec);
2436
308711e5 2437 nb_trace = lttv_traceset_number(traceset);
2438 for(i = 0 ; i < nb_trace ; i++) {
2439 tcs = (LttvTraceState *)self->parent.traces[i];
2440
2a2fa4f0 2441 if(ltt_time_compare(t, *(tcs->max_time_state_recomputed_in_seek)) < 0) {
2442 saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a,
2443 LTTV_STATE_SAVED_STATES);
2444 min_pos = -1;
2445
2446 if(saved_states_tree) {
dd025f91 2447 max_pos = lttv_attribute_get_number(saved_states_tree) - 1;
2448 mid_pos = max_pos / 2;
2449 while(min_pos < max_pos) {
c0cb4d12 2450 type = lttv_attribute_get(saved_states_tree, mid_pos, &name, &value,
2451 &is_named);
dd025f91 2452 g_assert(type == LTTV_GOBJECT);
2453 saved_state_tree = *((LttvAttribute **)(value.v_gobject));
2454 type = lttv_attribute_get_by_name(saved_state_tree, LTTV_STATE_TIME,
2455 &value);
2456 g_assert(type == LTTV_TIME);
2457 if(ltt_time_compare(*(value.v_time), t) < 0) {
2458 min_pos = mid_pos;
2459 closest_tree = saved_state_tree;
2460 }
2461 else max_pos = mid_pos - 1;
2462
2463 mid_pos = (min_pos + max_pos + 1) / 2;
2464 }
2a2fa4f0 2465 }
dd025f91 2466
2a2fa4f0 2467 /* restore the closest earlier saved state */
f95bc830 2468 if(min_pos != -1) {
2469 lttv_state_restore(tcs, closest_tree);
728d0c3e 2470 call_rest = 1;
f95bc830 2471 }
dd025f91 2472
2a2fa4f0 2473 /* There is no saved state, yet we want to have it. Restart at T0 */
dd025f91 2474 else {
2475 restore_init_state(tcs);
2476 lttv_process_trace_seek_time(&(tcs->parent), ltt_time_zero);
308711e5 2477 }
9444deae 2478 }
dd025f91 2479 /* We want to seek quickly without restoring/updating the state */
2480 else {
308711e5 2481 restore_init_state(tcs);
dd025f91 2482 lttv_process_trace_seek_time(&(tcs->parent), t);
308711e5 2483 }
308711e5 2484 }
728d0c3e 2485 if(!call_rest) g_info("NOT Calling restore");
308711e5 2486}
2487
2488
2489static void
2490traceset_state_instance_init (GTypeInstance *instance, gpointer g_class)
2491{
2492}
2493
2494
2495static void
2496traceset_state_finalize (LttvTracesetState *self)
2497{
2498 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))->
2499 finalize(G_OBJECT(self));
2500}
2501
2502
2503static void
2504traceset_state_class_init (LttvTracesetContextClass *klass)
2505{
2506 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
2507
2508 gobject_class->finalize = (void (*)(GObject *self)) traceset_state_finalize;
2509 klass->init = (void (*)(LttvTracesetContext *self, LttvTraceset *ts))init;
2510 klass->fini = (void (*)(LttvTracesetContext *self))fini;
2511 klass->new_traceset_context = new_traceset_context;
2512 klass->new_trace_context = new_trace_context;
2513 klass->new_tracefile_context = new_tracefile_context;
2514}
2515
2516
2517GType
2518lttv_traceset_state_get_type(void)
2519{
2520 static GType type = 0;
2521 if (type == 0) {
2522 static const GTypeInfo info = {
2523 sizeof (LttvTracesetStateClass),
2524 NULL, /* base_init */
2525 NULL, /* base_finalize */
2526 (GClassInitFunc) traceset_state_class_init, /* class_init */
2527 NULL, /* class_finalize */
2528 NULL, /* class_data */
dbb7bb09 2529 sizeof (LttvTracesetState),
308711e5 2530 0, /* n_preallocs */
00e74b69 2531 (GInstanceInitFunc) traceset_state_instance_init, /* instance_init */
2532 NULL /* value handling */
308711e5 2533 };
2534
2535 type = g_type_register_static (LTTV_TRACESET_CONTEXT_TYPE, "LttvTracesetStateType",
2536 &info, 0);
2537 }
2538 return type;
2539}
2540
2541
2542static void
2543trace_state_instance_init (GTypeInstance *instance, gpointer g_class)
2544{
2545}
2546
2547
2548static void
2549trace_state_finalize (LttvTraceState *self)
2550{
2551 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_CONTEXT_TYPE))->
2552 finalize(G_OBJECT(self));
2553}
2554
2555
2556static void
2557trace_state_class_init (LttvTraceStateClass *klass)
2558{
2559 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
2560
2561 gobject_class->finalize = (void (*)(GObject *self)) trace_state_finalize;
2562 klass->state_save = state_save;
2563 klass->state_restore = state_restore;
2564 klass->state_saved_free = state_saved_free;
2565}
2566
2567
2568GType
2569lttv_trace_state_get_type(void)
2570{
2571 static GType type = 0;
2572 if (type == 0) {
2573 static const GTypeInfo info = {
2574 sizeof (LttvTraceStateClass),
2575 NULL, /* base_init */
2576 NULL, /* base_finalize */
2577 (GClassInitFunc) trace_state_class_init, /* class_init */
2578 NULL, /* class_finalize */
2579 NULL, /* class_data */
2580 sizeof (LttvTraceState),
2581 0, /* n_preallocs */
00e74b69 2582 (GInstanceInitFunc) trace_state_instance_init, /* instance_init */
2583 NULL /* value handling */
308711e5 2584 };
2585
2586 type = g_type_register_static (LTTV_TRACE_CONTEXT_TYPE,
2587 "LttvTraceStateType", &info, 0);
2588 }
2589 return type;
2590}
2591
2592
2593static void
2594tracefile_state_instance_init (GTypeInstance *instance, gpointer g_class)
2595{
2596}
2597
2598
2599static void
2600tracefile_state_finalize (LttvTracefileState *self)
2601{
2602 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_CONTEXT_TYPE))->
2603 finalize(G_OBJECT(self));
2604}
2605
2606
2607static void
2608tracefile_state_class_init (LttvTracefileStateClass *klass)
2609{
2610 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
2611
2612 gobject_class->finalize = (void (*)(GObject *self)) tracefile_state_finalize;
2613}
2614
2615
2616GType
2617lttv_tracefile_state_get_type(void)
2618{
2619 static GType type = 0;
2620 if (type == 0) {
2621 static const GTypeInfo info = {
2622 sizeof (LttvTracefileStateClass),
2623 NULL, /* base_init */
2624 NULL, /* base_finalize */
2625 (GClassInitFunc) tracefile_state_class_init, /* class_init */
2626 NULL, /* class_finalize */
2627 NULL, /* class_data */
2628 sizeof (LttvTracefileState),
2629 0, /* n_preallocs */
00e74b69 2630 (GInstanceInitFunc) tracefile_state_instance_init, /* instance_init */
2631 NULL /* value handling */
308711e5 2632 };
2633
2634 type = g_type_register_static (LTTV_TRACEFILE_CONTEXT_TYPE,
2635 "LttvTracefileStateType", &info, 0);
2636 }
2637 return type;
2638}
2639
2640
08b1c66e 2641static void module_init()
ffd54a90 2642{
83e160f2 2643 LTTV_STATE_UNNAMED = g_quark_from_string("UNNAMED");
b3fd4c02 2644 LTTV_STATE_MODE_UNKNOWN = g_quark_from_string("MODE_UNKNOWN");
2645 LTTV_STATE_USER_MODE = g_quark_from_string("USER_MODE");
2646 LTTV_STATE_SYSCALL = g_quark_from_string("SYSCALL");
2647 LTTV_STATE_TRAP = g_quark_from_string("TRAP");
2648 LTTV_STATE_IRQ = g_quark_from_string("IRQ");
2649 LTTV_STATE_SOFT_IRQ = g_quark_from_string("SOFTIRQ");
2650 LTTV_STATE_SUBMODE_UNKNOWN = g_quark_from_string("UNKNOWN");
2651 LTTV_STATE_SUBMODE_NONE = g_quark_from_string("NONE");
2652 LTTV_STATE_WAIT_FORK = g_quark_from_string("WAIT_FORK");
2653 LTTV_STATE_WAIT_CPU = g_quark_from_string("WAIT_CPU");
2654 LTTV_STATE_EXIT = g_quark_from_string("EXIT");
2655 LTTV_STATE_ZOMBIE = g_quark_from_string("ZOMBIE");
2656 LTTV_STATE_WAIT = g_quark_from_string("WAIT");
2657 LTTV_STATE_RUN = g_quark_from_string("RUN");
2658 LTTV_STATE_DEAD = g_quark_from_string("DEAD");
e62e7f3a 2659 LTTV_STATE_USER_THREAD = g_quark_from_string("USER_THREAD");
2660 LTTV_STATE_KERNEL_THREAD = g_quark_from_string("KERNEL_THREAD");
308711e5 2661 LTTV_STATE_TRACEFILES = g_quark_from_string("tracefiles");
2662 LTTV_STATE_PROCESSES = g_quark_from_string("processes");
2663 LTTV_STATE_PROCESS = g_quark_from_string("process");
348c6ba8 2664 LTTV_STATE_RUNNING_PROCESS = g_quark_from_string("running_process");
308711e5 2665 LTTV_STATE_EVENT = g_quark_from_string("event");
2666 LTTV_STATE_SAVED_STATES = g_quark_from_string("saved states");
dbb7bb09 2667 LTTV_STATE_SAVED_STATES_TIME = g_quark_from_string("saved states time");
308711e5 2668 LTTV_STATE_TIME = g_quark_from_string("time");
ffd54a90 2669 LTTV_STATE_HOOKS = g_quark_from_string("saved state hooks");
f95bc830 2670 LTTV_STATE_NAME_TABLES = g_quark_from_string("name tables");
2671 LTTV_STATE_TRACE_STATE_USE_COUNT =
2672 g_quark_from_string("trace_state_use_count");
eed2ef37 2673
2674
2675 LTT_FACILITY_KERNEL = g_quark_from_string("kernel");
f5d7967f 2676 LTT_FACILITY_KERNEL_ARCH = g_quark_from_string("kernel_arch");
eed2ef37 2677 LTT_FACILITY_PROCESS = g_quark_from_string("process");
f4b88a7d 2678 LTT_FACILITY_FS = g_quark_from_string("fs");
b3fd4c02 2679 LTT_FACILITY_STATEDUMP = g_quark_from_string("statedump");
302efbad 2680 LTT_FACILITY_USER_GENERIC = g_quark_from_string("user_generic");
eed2ef37 2681
2682
2683 LTT_EVENT_SYSCALL_ENTRY = g_quark_from_string("syscall_entry");
2684 LTT_EVENT_SYSCALL_EXIT = g_quark_from_string("syscall_exit");
2685 LTT_EVENT_TRAP_ENTRY = g_quark_from_string("trap_entry");
2686 LTT_EVENT_TRAP_EXIT = g_quark_from_string("trap_exit");
2687 LTT_EVENT_IRQ_ENTRY = g_quark_from_string("irq_entry");
2688 LTT_EVENT_IRQ_EXIT = g_quark_from_string("irq_exit");
faf074a3 2689 LTT_EVENT_SOFT_IRQ_ENTRY = g_quark_from_string("soft_irq_entry");
2690 LTT_EVENT_SOFT_IRQ_EXIT = g_quark_from_string("soft_irq_exit");
eed2ef37 2691 LTT_EVENT_SCHEDCHANGE = g_quark_from_string("schedchange");
2692 LTT_EVENT_FORK = g_quark_from_string("fork");
7bfd7820 2693 LTT_EVENT_KERNEL_THREAD = g_quark_from_string("kernel_thread");
eed2ef37 2694 LTT_EVENT_EXIT = g_quark_from_string("exit");
2695 LTT_EVENT_FREE = g_quark_from_string("free");
f4b88a7d 2696 LTT_EVENT_EXEC = g_quark_from_string("exec");
b3fd4c02 2697 LTT_EVENT_ENUM_PROCESS_STATE = g_quark_from_string("enumerate_process_state");
302efbad 2698 LTT_EVENT_FUNCTION_ENTRY = g_quark_from_string("function_entry");
2699 LTT_EVENT_FUNCTION_EXIT = g_quark_from_string("function_exit");
eed2ef37 2700
2701
2702 LTT_FIELD_SYSCALL_ID = g_quark_from_string("syscall_id");
2703 LTT_FIELD_TRAP_ID = g_quark_from_string("trap_id");
2704 LTT_FIELD_IRQ_ID = g_quark_from_string("irq_id");
faf074a3 2705 LTT_FIELD_SOFT_IRQ_ID = g_quark_from_string("softirq_id");
eed2ef37 2706 LTT_FIELD_OUT = g_quark_from_string("out");
2707 LTT_FIELD_IN = g_quark_from_string("in");
2708 LTT_FIELD_OUT_STATE = g_quark_from_string("out_state");
2709 LTT_FIELD_PARENT_PID = g_quark_from_string("parent_pid");
2710 LTT_FIELD_CHILD_PID = g_quark_from_string("child_pid");
2711 LTT_FIELD_PID = g_quark_from_string("pid");
f4b88a7d 2712 LTT_FIELD_FILENAME = g_quark_from_string("filename");
b3fd4c02 2713 LTT_FIELD_NAME = g_quark_from_string("name");
e62e7f3a 2714 LTT_FIELD_TYPE = g_quark_from_string("type");
b3fd4c02 2715 LTT_FIELD_MODE = g_quark_from_string("mode");
2716 LTT_FIELD_SUBMODE = g_quark_from_string("submode");
2717 LTT_FIELD_STATUS = g_quark_from_string("status");
302efbad 2718 LTT_FIELD_THIS_FN = g_quark_from_string("this_fn");
2719 LTT_FIELD_CALL_SITE = g_quark_from_string("call_site");
eed2ef37 2720
ffd54a90 2721}
dc877563 2722
08b1c66e 2723static void module_destroy()
ffd54a90 2724{
2725}
dc877563 2726
2727
08b1c66e 2728LTTV_MODULE("state", "State computation", \
2729 "Update the system state, possibly saving it at intervals", \
2730 module_init, module_destroy)
2731
dc877563 2732
2733
This page took 0.182842 seconds and 4 git commands to generate.