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