format update
[lttv.git] / ltt / branches / poly / lttv / lttv / state.c
CommitLineData
9c312311 1/* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Michel Dagenais
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
16 * MA 02111-1307, USA.
17 */
18
4e4d11b3 19#ifdef HAVE_CONFIG_H
20#include <config.h>
21#endif
dc877563 22
08b1c66e 23#include <lttv/lttv.h>
24#include <lttv/module.h>
dc877563 25#include <lttv/state.h>
ba576a78 26#include <ltt/facility.h>
27#include <ltt/trace.h>
308711e5 28#include <ltt/event.h>
a5dcde2f 29#include <ltt/type.h>
f95bc830 30#include <stdio.h>
b3fd4c02 31#include <string.h>
dc877563 32
e8f2280c 33#define PREALLOCATED_EXECUTION_STACK 10
34
eed2ef37 35/* Facilities Quarks */
36
37GQuark
38 LTT_FACILITY_KERNEL,
f5d7967f 39 LTT_FACILITY_KERNEL_ARCH,
f4b88a7d 40 LTT_FACILITY_PROCESS,
b3fd4c02 41 LTT_FACILITY_FS,
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) {
ab893fb1 1339 child_process = 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 }
ab893fb1 1352 g_assert(child_process->name == LTTV_STATE_UNNAMED);
1353 child_process->name = process->name;
4ad73431 1354
dc877563 1355 return FALSE;
1356}
1357
1358
eed2ef37 1359static gboolean process_exit(void *hook_data, void *call_data)
dc877563 1360{
eed2ef37 1361 LttvTracefileState *s = (LttvTracefileState *)call_data;
1362 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
d052ffc3 1363 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
eed2ef37 1364 LttField *f;
1365 guint pid;
348c6ba8 1366 guint cpu = ltt_tracefile_num(s->parent.tf);
1367 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
1368 LttvProcessState *process = ts->running_process[cpu];
eed2ef37 1369
1370 pid = ltt_event_get_unsigned(e, thf->f1);
1371
1372 // FIXME : Add this test in the "known state" section
348c6ba8 1373 // g_assert(process->pid == pid);
eed2ef37 1374
348c6ba8 1375 if(likely(process != NULL)) {
1376 process->state->s = LTTV_STATE_EXIT;
2cdc690b 1377 }
1378 return FALSE;
2cdc690b 1379}
1380
eed2ef37 1381static gboolean process_free(void *hook_data, void *call_data)
2da61677 1382{
eed2ef37 1383 LttvTracefileState *s = (LttvTracefileState *)call_data;
348c6ba8 1384 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
eed2ef37 1385 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
d052ffc3 1386 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
2da61677 1387 guint release_pid;
1388 LttvProcessState *process;
1389
1390 /* PID of the process to release */
eed2ef37 1391 release_pid = ltt_event_get_unsigned(e, thf->f1);
15b3d537 1392
1393 g_assert(release_pid != 0);
2da61677 1394
348c6ba8 1395 process = lttv_state_find_process(ts, ANY_CPU, release_pid);
2da61677 1396
1397 if(likely(process != NULL)) {
1398 /* release_task is happening at kernel level : we can now safely release
1399 * the data structure of the process */
5562ddce 1400 //This test is fun, though, as it may happen that
1401 //at time t : CPU 0 : process_free
1402 //at time t+150ns : CPU 1 : schedule out
1403 //Clearly due to time imprecision, we disable it. (Mathieu)
1404 //If this weird case happen, we have no choice but to put the
1405 //Currently running process on the cpu to 0.
791dffa6 1406 //I re-enable it following time precision fixes. (Mathieu)
1407 //Well, in the case where an process is freed by a process on another CPU
1408 //and still scheduled, it happens that this is the schedchange that will
1409 //drop the last reference count. Do not free it here!
0bd2f89c 1410 guint num_cpus = ltt_trace_get_num_cpu(ts->parent.t);
1411 guint i;
1412 for(i=0; i< num_cpus; i++) {
5562ddce 1413 //g_assert(process != ts->running_process[i]);
1414 if(process == ts->running_process[i]) {
791dffa6 1415 //ts->running_process[i] = lttv_state_find_process(ts, i, 0);
1416 break;
5562ddce 1417 }
0bd2f89c 1418 }
791dffa6 1419 if(i == num_cpus) /* process is not scheduled */
1420 exit_process(s, process);
2da61677 1421 }
1422
1423 return FALSE;
1424}
1425
f4b88a7d 1426
1427static gboolean process_exec(void *hook_data, void *call_data)
1428{
1429 LttvTracefileState *s = (LttvTracefileState *)call_data;
1430 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
1431 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
1432 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
743e50fd 1433 //gchar *name;
f4b88a7d 1434 guint cpu = ltt_tracefile_num(s->parent.tf);
1435 LttvProcessState *process = ts->running_process[cpu];
1436
1437 /* PID of the process to release */
743e50fd 1438 guint64 name_len = ltt_event_field_element_number(e, thf->f1);
1439 //name = ltt_event_get_string(e, thf->f1);
f2923fb2 1440 LttField *child = ltt_event_field_element_select(e, thf->f1, 0);
1441 gchar *name_begin =
1442 (gchar*)(ltt_event_data(e)+ltt_event_field_offset(e, child));
743e50fd 1443 gchar *null_term_name = g_new(gchar, name_len+1);
1444 memcpy(null_term_name, name_begin, name_len);
1445 null_term_name[name_len] = '\0';
1446
1447 process->name = g_quark_from_string(null_term_name);
f2923fb2 1448 g_free(null_term_name);
f4b88a7d 1449 return FALSE;
1450}
1451
b3fd4c02 1452static gboolean enum_process_state(void *hook_data, void *call_data)
1453{
1454 LttvTracefileState *s = (LttvTracefileState *)call_data;
1455 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
1456 //It's slow : optimise later by doing this before reading trace.
1457 LttEventType *et = ltt_event_eventtype(e);
1458 //
1459 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
1460 guint parent_pid;
1461 guint pid;
1462 gchar * command;
1463 guint cpu = ltt_tracefile_num(s->parent.tf);
1464 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
1465 LttvProcessState *process = ts->running_process[cpu];
1466 LttvProcessState *parent_process;
1467 LttField *f4, *f5, *f6;
1468 GQuark mode, submode, status;
f4b88a7d 1469
b3fd4c02 1470 /* PID */
1471 pid = ltt_event_get_unsigned(e, thf->f1);
f4b88a7d 1472
b3fd4c02 1473 /* Parent PID */
1474 parent_pid = ltt_event_get_unsigned(e, thf->f2);
1475
1476 /* Command name */
1477 command = ltt_event_get_string(e, thf->f3);
1478
1479 /* mode */
1480 f4 = ltt_eventtype_field_by_name(et, LTT_FIELD_MODE);
1481 mode = ltt_enum_string_get(ltt_field_type(f4),
1482 ltt_event_get_unsigned(e, f4));
1483
1484 /* submode */
1485 f5 = ltt_eventtype_field_by_name(et, LTT_FIELD_SUBMODE);
1486 submode = ltt_enum_string_get(ltt_field_type(f5),
1487 ltt_event_get_unsigned(e, f5));
1488
1489 /* status */
1490 f6 = ltt_eventtype_field_by_name(et, LTT_FIELD_STATUS);
1491 status = ltt_enum_string_get(ltt_field_type(f6),
1492 ltt_event_get_unsigned(e, f6));
1493
1494 /* The process might exist if a process was forked while performing the sate dump. */
1495 process = lttv_state_find_process(ts, ANY_CPU, pid);
1496 if(process == NULL) {
1497 parent_process = lttv_state_find_process(ts, ANY_CPU, parent_pid);
1498 process = lttv_state_create_process(ts, parent_process, cpu,
1499 pid, g_quark_from_string(command),
1500 &s->parent.timestamp);
1501
1502 /* Keep the stack bottom : a running user mode */
ab893fb1 1503#if 0
1504 /* Disabled because of inconsistencies in the current statedump states. */
b3fd4c02 1505 if(mode == LTTV_STATE_USER_MODE) {
1506 /* Only keep the bottom */
1507 process->execution_stack = g_array_set_size(process->execution_stack, 1);
1508 } else {
1509 /* On top of it : */
1510 LttvExecutionState *es;
1511 es = process->state = &g_array_index(process->execution_stack,
1512 LttvExecutionState, 1);
1513 es->t = mode;
1514 es->s = status;
1515 es->n = submode;
1516 }
ab893fb1 1517#endif //0
b3fd4c02 1518
ab893fb1 1519 /* UNKNOWN STATE */
1520 {
1521 LttvExecutionState *es;
1522 es = process->state = &g_array_index(process->execution_stack,
1523 LttvExecutionState, 1);
1524 es->t = LTTV_STATE_MODE_UNKNOWN;
1525 es->s = LTTV_STATE_UNNAMED;
1526 es->n = LTTV_STATE_SUBMODE_UNKNOWN;
1527 }
b3fd4c02 1528 } else {
1529 /* The process has already been created :
1530 * Probably was forked while dumping the process state or
1531 * was simply scheduled in prior to get the state dump event.
1532 */
1533 process->ppid = parent_pid;
1534 process->name = g_quark_from_string(command);
1535 /* Don't mess around with the stack, it will eventually become
1536 * ok after the end of state dump. */
1537 }
1538
1539 return FALSE;
1540}
f4b88a7d 1541
58c88a41 1542gint lttv_state_hook_add_event_hooks(void *hook_data, void *call_data)
1543{
1544 LttvTracesetState *tss = (LttvTracesetState*)(call_data);
1545
1546 lttv_state_add_event_hooks(tss);
1547
1548 return 0;
1549}
dc877563 1550
308711e5 1551void lttv_state_add_event_hooks(LttvTracesetState *self)
dc877563 1552{
ba576a78 1553 LttvTraceset *traceset = self->parent.ts;
dc877563 1554
eed2ef37 1555 guint i, j, k, l, nb_trace, nb_tracefile;
dc877563 1556
ba576a78 1557 LttvTraceState *ts;
dc877563 1558
ba576a78 1559 LttvTracefileState *tfs;
dc877563 1560
dc877563 1561 GArray *hooks;
1562
eed2ef37 1563 LttvTraceHookByFacility *thf;
1564
1565 LttvTraceHook *hook;
dc877563 1566
1567 LttvAttributeValue val;
1568
9d239bd9 1569 gint ret;
1570
ba576a78 1571 nb_trace = lttv_traceset_number(traceset);
dc877563 1572 for(i = 0 ; i < nb_trace ; i++) {
ba576a78 1573 ts = (LttvTraceState *)self->parent.traces[i];
dc877563 1574
1575 /* Find the eventtype id for the following events and register the
1576 associated by id hooks. */
1577
b3fd4c02 1578 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 14);
1579 hooks = g_array_set_size(hooks, 14);
b445142a 1580
9d239bd9 1581 ret = lttv_trace_find_hook(ts->parent.t,
f5d7967f 1582 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_ENTRY,
eed2ef37 1583 LTT_FIELD_SYSCALL_ID, 0, 0,
2c82c4dc 1584 syscall_entry, NULL, &g_array_index(hooks, LttvTraceHook, 0));
9d239bd9 1585 g_assert(!ret);
cbe7c836 1586
9d239bd9 1587 ret = lttv_trace_find_hook(ts->parent.t,
f5d7967f 1588 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_EXIT,
eed2ef37 1589 0, 0, 0,
2c82c4dc 1590 syscall_exit, NULL, &g_array_index(hooks, LttvTraceHook, 1));
9d239bd9 1591 g_assert(!ret);
cbe7c836 1592
9d239bd9 1593 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 1594 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY,
1595 LTT_FIELD_TRAP_ID, 0, 0,
2c82c4dc 1596 trap_entry, NULL, &g_array_index(hooks, LttvTraceHook, 2));
9d239bd9 1597 g_assert(!ret);
cbe7c836 1598
9d239bd9 1599 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 1600 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT,
1601 0, 0, 0,
2c82c4dc 1602 trap_exit, NULL, &g_array_index(hooks, LttvTraceHook, 3));
9d239bd9 1603 g_assert(!ret);
cbe7c836 1604
9d239bd9 1605 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 1606 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
1607 LTT_FIELD_IRQ_ID, 0, 0,
2c82c4dc 1608 irq_entry, NULL, &g_array_index(hooks, LttvTraceHook, 4));
9d239bd9 1609 g_assert(!ret);
cbe7c836 1610
9d239bd9 1611 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 1612 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
1613 0, 0, 0,
2c82c4dc 1614 irq_exit, NULL, &g_array_index(hooks, LttvTraceHook, 5));
9d239bd9 1615 g_assert(!ret);
cbe7c836 1616
faf074a3 1617 ret = lttv_trace_find_hook(ts->parent.t,
1618 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_ENTRY,
1619 LTT_FIELD_SOFT_IRQ_ID, 0, 0,
1620 soft_irq_entry, NULL, &g_array_index(hooks, LttvTraceHook, 6));
1621 g_assert(!ret);
1622
1623 ret = lttv_trace_find_hook(ts->parent.t,
1624 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_EXIT,
1625 0, 0, 0,
1626 soft_irq_exit, NULL, &g_array_index(hooks, LttvTraceHook, 7));
1627 g_assert(!ret);
1628
9d239bd9 1629 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 1630 LTT_FACILITY_PROCESS, LTT_EVENT_SCHEDCHANGE,
1631 LTT_FIELD_OUT, LTT_FIELD_IN, LTT_FIELD_OUT_STATE,
faf074a3 1632 schedchange, NULL, &g_array_index(hooks, LttvTraceHook, 8));
9d239bd9 1633 g_assert(!ret);
cbe7c836 1634
9d239bd9 1635 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 1636 LTT_FACILITY_PROCESS, LTT_EVENT_FORK,
1637 LTT_FIELD_PARENT_PID, LTT_FIELD_CHILD_PID, 0,
faf074a3 1638 process_fork, NULL, &g_array_index(hooks, LttvTraceHook, 9));
9d239bd9 1639 g_assert(!ret);
eed2ef37 1640
9d239bd9 1641 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 1642 LTT_FACILITY_PROCESS, LTT_EVENT_EXIT,
1643 LTT_FIELD_PID, 0, 0,
faf074a3 1644 process_exit, NULL, &g_array_index(hooks, LttvTraceHook, 10));
9d239bd9 1645 g_assert(!ret);
eed2ef37 1646
9d239bd9 1647 ret = lttv_trace_find_hook(ts->parent.t,
eed2ef37 1648 LTT_FACILITY_PROCESS, LTT_EVENT_FREE,
1649 LTT_FIELD_PID, 0, 0,
faf074a3 1650 process_free, NULL, &g_array_index(hooks, LttvTraceHook, 11));
9d239bd9 1651 g_assert(!ret);
2cdc690b 1652
f4b88a7d 1653 ret = lttv_trace_find_hook(ts->parent.t,
1654 LTT_FACILITY_FS, LTT_EVENT_EXEC,
1655 LTT_FIELD_FILENAME, 0, 0,
faf074a3 1656 process_exec, NULL, &g_array_index(hooks, LttvTraceHook, 12));
f4b88a7d 1657 g_assert(!ret);
1658
b3fd4c02 1659 /* statedump-related hooks */
1660 ret = lttv_trace_find_hook(ts->parent.t,
1661 LTT_FACILITY_STATEDUMP, LTT_EVENT_ENUM_PROCESS_STATE,
1662 LTT_FIELD_PID, LTT_FIELD_PARENT_PID, LTT_FIELD_NAME,
1663 enum_process_state, NULL, &g_array_index(hooks, LttvTraceHook, 13));
1664 g_assert(!ret);
f4b88a7d 1665
b3fd4c02 1666
a5ba1787 1667 /* Add these hooks to each event_by_id hooks list */
dc877563 1668
eed2ef37 1669 nb_tracefile = ts->parent.tracefiles->len;
dbb7bb09 1670
dc877563 1671 for(j = 0 ; j < nb_tracefile ; j++) {
eed2ef37 1672 tfs =
9d239bd9 1673 LTTV_TRACEFILE_STATE(g_array_index(ts->parent.tracefiles,
1674 LttvTracefileContext*, j));
dc877563 1675
1676 for(k = 0 ; k < hooks->len ; k++) {
eed2ef37 1677 hook = &g_array_index(hooks, LttvTraceHook, k);
1678 for(l=0;l<hook->fac_list->len;l++) {
1679 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1680 lttv_hooks_add(
1681 lttv_hooks_by_id_find(tfs->parent.event_by_id, thf->id),
1682 thf->h,
d052ffc3 1683 thf,
eed2ef37 1684 LTTV_PRIO_STATE);
1685 }
ffd54a90 1686 }
dc877563 1687 }
f0b795e0 1688 lttv_attribute_find(ts->parent.a, LTTV_STATE_HOOKS, LTTV_POINTER, &val);
ba576a78 1689 *(val.v_pointer) = hooks;
dc877563 1690 }
1691}
1692
58c88a41 1693gint lttv_state_hook_remove_event_hooks(void *hook_data, void *call_data)
1694{
1695 LttvTracesetState *tss = (LttvTracesetState*)(call_data);
1696
1697 lttv_state_remove_event_hooks(tss);
1698
1699 return 0;
1700}
dc877563 1701
308711e5 1702void lttv_state_remove_event_hooks(LttvTracesetState *self)
dc877563 1703{
ba576a78 1704 LttvTraceset *traceset = self->parent.ts;
dc877563 1705
eed2ef37 1706 guint i, j, k, l, nb_trace, nb_tracefile;
dc877563 1707
ba576a78 1708 LttvTraceState *ts;
dc877563 1709
ba576a78 1710 LttvTracefileState *tfs;
dc877563 1711
dc877563 1712 GArray *hooks;
1713
eed2ef37 1714 LttvTraceHook *hook;
1715
1716 LttvTraceHookByFacility *thf;
dc877563 1717
1718 LttvAttributeValue val;
1719
ba576a78 1720 nb_trace = lttv_traceset_number(traceset);
dc877563 1721 for(i = 0 ; i < nb_trace ; i++) {
021eeb41 1722 ts = LTTV_TRACE_STATE(self->parent.traces[i]);
f0b795e0 1723 lttv_attribute_find(ts->parent.a, LTTV_STATE_HOOKS, LTTV_POINTER, &val);
ba576a78 1724 hooks = *(val.v_pointer);
dc877563 1725
a5ba1787 1726 /* Remove these hooks from each event_by_id hooks list */
dc877563 1727
eed2ef37 1728 nb_tracefile = ts->parent.tracefiles->len;
dbb7bb09 1729
dc877563 1730 for(j = 0 ; j < nb_tracefile ; j++) {
eed2ef37 1731 tfs =
cb03932a 1732 LTTV_TRACEFILE_STATE(g_array_index(ts->parent.tracefiles,
1733 LttvTracefileContext*, j));
dc877563 1734
1735 for(k = 0 ; k < hooks->len ; k++) {
eed2ef37 1736 hook = &g_array_index(hooks, LttvTraceHook, k);
1737 for(l=0;l<hook->fac_list->len;l++) {
1738 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1739
1740 lttv_hooks_remove_data(
1741 lttv_hooks_by_id_find(tfs->parent.event_by_id, thf->id),
1742 thf->h,
d052ffc3 1743 thf);
eed2ef37 1744 }
ffd54a90 1745 }
dc877563 1746 }
1986f254 1747 for(k = 0 ; k < hooks->len ; k++)
1748 lttv_trace_hook_destroy(&g_array_index(hooks, LttvTraceHook, k));
dc877563 1749 g_array_free(hooks, TRUE);
1750 }
1751}
1752
eed2ef37 1753static gboolean state_save_event_hook(void *hook_data, void *call_data)
1754{
1755 guint *event_count = (guint*)hook_data;
1756
1757 /* Only save at LTTV_STATE_SAVE_INTERVAL */
1758 if(likely((*event_count)++ < LTTV_STATE_SAVE_INTERVAL))
1759 return FALSE;
1760 else
18c87975 1761 *event_count = 0;
eed2ef37 1762
1763 LttvTracefileState *self = (LttvTracefileState *)call_data;
1764
1765 LttvTracefileState *tfcs;
1766
1767 LttvTraceState *tcs = (LttvTraceState *)(self->parent.t_context);
1768
1769 LttEventPosition *ep;
1770
1771 guint i;
1772
1773 LttTracefile *tf;
1774
1775 LttvAttribute *saved_states_tree, *saved_state_tree;
1776
1777 LttvAttributeValue value;
1778
1779 saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a,
1780 LTTV_STATE_SAVED_STATES);
1781 saved_state_tree = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
1782 value = lttv_attribute_add(saved_states_tree,
1783 lttv_attribute_get_number(saved_states_tree), LTTV_GOBJECT);
1784 *(value.v_gobject) = (GObject *)saved_state_tree;
1785 value = lttv_attribute_add(saved_state_tree, LTTV_STATE_TIME, LTTV_TIME);
1786 *(value.v_time) = self->parent.timestamp;
1787 lttv_state_save(tcs, saved_state_tree);
1788 g_debug("Saving state at time %lu.%lu", self->parent.timestamp.tv_sec,
1789 self->parent.timestamp.tv_nsec);
1790
1791 *(tcs->max_time_state_recomputed_in_seek) = self->parent.timestamp;
1792
1793 return FALSE;
1794}
1795
14aecf75 1796static gboolean state_save_after_trace_hook(void *hook_data, void *call_data)
1797{
1798 LttvTraceState *tcs = (LttvTraceState *)(call_data);
1799
1800 *(tcs->max_time_state_recomputed_in_seek) = tcs->parent.time_span.end_time;
1801
1802 return FALSE;
1803}
1804
eed2ef37 1805#if 0
08b1c66e 1806static gboolean block_start(void *hook_data, void *call_data)
308711e5 1807{
dbb7bb09 1808 LttvTracefileState *self = (LttvTracefileState *)call_data;
308711e5 1809
dbb7bb09 1810 LttvTracefileState *tfcs;
308711e5 1811
dbb7bb09 1812 LttvTraceState *tcs = (LttvTraceState *)(self->parent.t_context);
1813
1814 LttEventPosition *ep;
308711e5 1815
dbb7bb09 1816 guint i, nb_block, nb_event, nb_tracefile;
308711e5 1817
1818 LttTracefile *tf;
1819
1820 LttvAttribute *saved_states_tree, *saved_state_tree;
1821
1822 LttvAttributeValue value;
1823
dbb7bb09 1824 ep = ltt_event_position_new();
eed2ef37 1825
1826 nb_tracefile = tcs->parent.tracefiles->len;
dbb7bb09 1827
1828 /* Count the number of events added since the last block end in any
1829 tracefile. */
1830
1831 for(i = 0 ; i < nb_tracefile ; i++) {
eed2ef37 1832 tfcs =
1833 LTTV_TRACEFILE_STATE(&g_array_index(tcs->parent.tracefiles,
1834 LttvTracefileContext, i));
dbb7bb09 1835 ltt_event_position(tfcs->parent.e, ep);
1836 ltt_event_position_get(ep, &nb_block, &nb_event, &tf);
1837 tcs->nb_event += nb_event - tfcs->saved_position;
1838 tfcs->saved_position = nb_event;
1839 }
1840 g_free(ep);
308711e5 1841
308711e5 1842 if(tcs->nb_event >= tcs->save_interval) {
1843 saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a,
1844 LTTV_STATE_SAVED_STATES);
1845 saved_state_tree = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
1846 value = lttv_attribute_add(saved_states_tree,
1847 lttv_attribute_get_number(saved_states_tree), LTTV_GOBJECT);
1848 *(value.v_gobject) = (GObject *)saved_state_tree;
1849 value = lttv_attribute_add(saved_state_tree, LTTV_STATE_TIME, LTTV_TIME);
dbb7bb09 1850 *(value.v_time) = self->parent.timestamp;
308711e5 1851 lttv_state_save(tcs, saved_state_tree);
1852 tcs->nb_event = 0;
08b1c66e 1853 g_debug("Saving state at time %lu.%lu", self->parent.timestamp.tv_sec,
1854 self->parent.timestamp.tv_nsec);
308711e5 1855 }
dbb7bb09 1856 *(tcs->max_time_state_recomputed_in_seek) = self->parent.timestamp;
308711e5 1857 return FALSE;
1858}
eed2ef37 1859#endif //0
308711e5 1860
eed2ef37 1861#if 0
08b1c66e 1862static gboolean block_end(void *hook_data, void *call_data)
1863{
1864 LttvTracefileState *self = (LttvTracefileState *)call_data;
1865
1866 LttvTraceState *tcs = (LttvTraceState *)(self->parent.t_context);
1867
1868 LttTracefile *tf;
1869
1870 LttEventPosition *ep;
1871
1872 guint nb_block, nb_event;
1873
1874 ep = ltt_event_position_new();
1875 ltt_event_position(self->parent.e, ep);
1876 ltt_event_position_get(ep, &nb_block, &nb_event, &tf);
1877 tcs->nb_event += nb_event - self->saved_position + 1;
1878 self->saved_position = 0;
1879 *(tcs->max_time_state_recomputed_in_seek) = self->parent.timestamp;
1880 g_free(ep);
00e74b69 1881
1882 return FALSE;
08b1c66e 1883}
eed2ef37 1884#endif //0
1885#if 0
308711e5 1886void lttv_state_save_add_event_hooks(LttvTracesetState *self)
1887{
1888 LttvTraceset *traceset = self->parent.ts;
1889
00e74b69 1890 guint i, j, nb_trace, nb_tracefile;
308711e5 1891
1892 LttvTraceState *ts;
1893
1894 LttvTracefileState *tfs;
1895
08b1c66e 1896 LttvTraceHook hook_start, hook_end;
308711e5 1897
1898 nb_trace = lttv_traceset_number(traceset);
1899 for(i = 0 ; i < nb_trace ; i++) {
1900 ts = (LttvTraceState *)self->parent.traces[i];
eed2ef37 1901
08b1c66e 1902 lttv_trace_find_hook(ts->parent.t, "core","block_start",NULL,
1903 NULL, NULL, block_start, &hook_start);
308711e5 1904 lttv_trace_find_hook(ts->parent.t, "core","block_end",NULL,
08b1c66e 1905 NULL, NULL, block_end, &hook_end);
308711e5 1906
eed2ef37 1907 nb_tracefile = ts->parent.tracefiles->len;
308711e5 1908
dbb7bb09 1909 for(j = 0 ; j < nb_tracefile ; j++) {
eed2ef37 1910 tfs =
1911 LTTV_TRACEFILE_STATE(&g_array_index(ts->parent.tracefiles,
1912 LttvTracefileContext, j));
a5ba1787 1913 lttv_hooks_add(lttv_hooks_by_id_find(tfs->parent.event_by_id,
eed2ef37 1914 hook_start.id), hook_start.h, NULL, LTTV_PRIO_STATE);
a5ba1787 1915 lttv_hooks_add(lttv_hooks_by_id_find(tfs->parent.event_by_id,
eed2ef37 1916 hook_end.id), hook_end.h, NULL, LTTV_PRIO_STATE);
1917 }
1918 }
1919}
1920#endif //0
1921
1922void lttv_state_save_add_event_hooks(LttvTracesetState *self)
1923{
1924 LttvTraceset *traceset = self->parent.ts;
1925
1926 guint i, j, nb_trace, nb_tracefile;
1927
1928 LttvTraceState *ts;
1929
1930 LttvTracefileState *tfs;
1931
1932
1933 nb_trace = lttv_traceset_number(traceset);
1934 for(i = 0 ; i < nb_trace ; i++) {
1935
1936 ts = (LttvTraceState *)self->parent.traces[i];
1937 nb_tracefile = ts->parent.tracefiles->len;
1938
3054461a 1939 guint *event_count = g_new(guint, 1);
1940 *event_count = 0;
1941
eed2ef37 1942 for(j = 0 ; j < nb_tracefile ; j++) {
1943 tfs =
cb03932a 1944 LTTV_TRACEFILE_STATE(g_array_index(ts->parent.tracefiles,
1945 LttvTracefileContext*, j));
eed2ef37 1946 lttv_hooks_add(tfs->parent.event,
1947 state_save_event_hook,
1948 event_count,
1949 LTTV_PRIO_STATE);
1950
308711e5 1951 }
1952 }
14aecf75 1953
1954 lttv_process_traceset_begin(&self->parent,
1955 NULL, NULL, NULL, NULL, NULL);
1956
308711e5 1957}
1958
b56b5fec 1959gint lttv_state_save_hook_add_event_hooks(void *hook_data, void *call_data)
1960{
1961 LttvTracesetState *tss = (LttvTracesetState*)(call_data);
1962
1963 lttv_state_save_add_event_hooks(tss);
1964
1965 return 0;
1966}
1967
308711e5 1968
eed2ef37 1969#if 0
308711e5 1970void lttv_state_save_remove_event_hooks(LttvTracesetState *self)
1971{
1972 LttvTraceset *traceset = self->parent.ts;
1973
00e74b69 1974 guint i, j, nb_trace, nb_tracefile;
308711e5 1975
1976 LttvTraceState *ts;
1977
1978 LttvTracefileState *tfs;
1979
08b1c66e 1980 LttvTraceHook hook_start, hook_end;
308711e5 1981
1982 nb_trace = lttv_traceset_number(traceset);
1983 for(i = 0 ; i < nb_trace ; i++) {
1984 ts = LTTV_TRACE_STATE(self->parent.traces[i]);
eed2ef37 1985
08b1c66e 1986 lttv_trace_find_hook(ts->parent.t, "core","block_start",NULL,
1987 NULL, NULL, block_start, &hook_start);
1988
308711e5 1989 lttv_trace_find_hook(ts->parent.t, "core","block_end",NULL,
08b1c66e 1990 NULL, NULL, block_end, &hook_end);
308711e5 1991
eed2ef37 1992 nb_tracefile = ts->parent.tracefiles->len;
308711e5 1993
dbb7bb09 1994 for(j = 0 ; j < nb_tracefile ; j++) {
eed2ef37 1995 tfs =
1996 LTTV_TRACEFILE_STATE(&g_array_index(ts->parent.tracefiles,
1997 LttvTracefileContext, j));
308711e5 1998 lttv_hooks_remove_data(lttv_hooks_by_id_find(
a5ba1787 1999 tfs->parent.event_by_id, hook_start.id), hook_start.h, NULL);
08b1c66e 2000 lttv_hooks_remove_data(lttv_hooks_by_id_find(
a5ba1787 2001 tfs->parent.event_by_id, hook_end.id), hook_end.h, NULL);
308711e5 2002 }
2003 }
2004}
eed2ef37 2005#endif //0
2006
2007void lttv_state_save_remove_event_hooks(LttvTracesetState *self)
2008{
2009 LttvTraceset *traceset = self->parent.ts;
2010
2011 guint i, j, nb_trace, nb_tracefile;
2012
2013 LttvTraceState *ts;
2014
2015 LttvTracefileState *tfs;
2016
14aecf75 2017 LttvHooks *after_trace = lttv_hooks_new();
2018
2019 lttv_hooks_add(after_trace,
2020 state_save_after_trace_hook,
2021 NULL,
2022 LTTV_PRIO_STATE);
2023
2024
2025 lttv_process_traceset_end(&self->parent,
2026 NULL, after_trace, NULL, NULL, NULL);
eed2ef37 2027
14aecf75 2028 lttv_hooks_destroy(after_trace);
2029
eed2ef37 2030 nb_trace = lttv_traceset_number(traceset);
2031 for(i = 0 ; i < nb_trace ; i++) {
2032
2033 ts = (LttvTraceState *)self->parent.traces[i];
2034 nb_tracefile = ts->parent.tracefiles->len;
2035
22b165e9 2036 guint *event_count = NULL;
eed2ef37 2037
2038 for(j = 0 ; j < nb_tracefile ; j++) {
2039 tfs =
cb03932a 2040 LTTV_TRACEFILE_STATE(g_array_index(ts->parent.tracefiles,
2041 LttvTracefileContext*, j));
eed2ef37 2042 event_count = lttv_hooks_remove(tfs->parent.event,
2043 state_save_event_hook);
eed2ef37 2044 }
22b165e9 2045 if(event_count) g_free(event_count);
eed2ef37 2046 }
2047}
308711e5 2048
b56b5fec 2049gint lttv_state_save_hook_remove_event_hooks(void *hook_data, void *call_data)
2050{
2051 LttvTracesetState *tss = (LttvTracesetState*)(call_data);
2052
2053 lttv_state_save_remove_event_hooks(tss);
2054
2055 return 0;
2056}
308711e5 2057
dd025f91 2058void lttv_state_traceset_seek_time_closest(LttvTracesetState *self, LttTime t)
308711e5 2059{
2060 LttvTraceset *traceset = self->parent.ts;
2061
00e74b69 2062 guint i, nb_trace;
308711e5 2063
2064 int min_pos, mid_pos, max_pos;
2065
728d0c3e 2066 guint call_rest = 0;
2067
308711e5 2068 LttvTraceState *tcs;
2069
2070 LttvAttributeValue value;
2071
2072 LttvAttributeType type;
2073
2074 LttvAttributeName name;
2075
2076 LttvAttribute *saved_states_tree, *saved_state_tree, *closest_tree;
2077
d448fce2 2078 //g_tree_destroy(self->parent.pqueue);
2079 //self->parent.pqueue = g_tree_new(compare_tracefile);
348c6ba8 2080
728d0c3e 2081 g_info("Entering seek_time_closest for time %lu.%lu", t.tv_sec, t.tv_nsec);
2082
308711e5 2083 nb_trace = lttv_traceset_number(traceset);
2084 for(i = 0 ; i < nb_trace ; i++) {
2085 tcs = (LttvTraceState *)self->parent.traces[i];
2086
2a2fa4f0 2087 if(ltt_time_compare(t, *(tcs->max_time_state_recomputed_in_seek)) < 0) {
2088 saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a,
2089 LTTV_STATE_SAVED_STATES);
2090 min_pos = -1;
2091
2092 if(saved_states_tree) {
dd025f91 2093 max_pos = lttv_attribute_get_number(saved_states_tree) - 1;
2094 mid_pos = max_pos / 2;
2095 while(min_pos < max_pos) {
2096 type = lttv_attribute_get(saved_states_tree, mid_pos, &name, &value);
2097 g_assert(type == LTTV_GOBJECT);
2098 saved_state_tree = *((LttvAttribute **)(value.v_gobject));
2099 type = lttv_attribute_get_by_name(saved_state_tree, LTTV_STATE_TIME,
2100 &value);
2101 g_assert(type == LTTV_TIME);
2102 if(ltt_time_compare(*(value.v_time), t) < 0) {
2103 min_pos = mid_pos;
2104 closest_tree = saved_state_tree;
2105 }
2106 else max_pos = mid_pos - 1;
2107
2108 mid_pos = (min_pos + max_pos + 1) / 2;
2109 }
2a2fa4f0 2110 }
dd025f91 2111
2a2fa4f0 2112 /* restore the closest earlier saved state */
f95bc830 2113 if(min_pos != -1) {
2114 lttv_state_restore(tcs, closest_tree);
728d0c3e 2115 call_rest = 1;
f95bc830 2116 }
dd025f91 2117
2a2fa4f0 2118 /* There is no saved state, yet we want to have it. Restart at T0 */
dd025f91 2119 else {
2120 restore_init_state(tcs);
2121 lttv_process_trace_seek_time(&(tcs->parent), ltt_time_zero);
308711e5 2122 }
9444deae 2123 }
dd025f91 2124 /* We want to seek quickly without restoring/updating the state */
2125 else {
308711e5 2126 restore_init_state(tcs);
dd025f91 2127 lttv_process_trace_seek_time(&(tcs->parent), t);
308711e5 2128 }
308711e5 2129 }
728d0c3e 2130 if(!call_rest) g_info("NOT Calling restore");
308711e5 2131}
2132
2133
2134static void
2135traceset_state_instance_init (GTypeInstance *instance, gpointer g_class)
2136{
2137}
2138
2139
2140static void
2141traceset_state_finalize (LttvTracesetState *self)
2142{
2143 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))->
2144 finalize(G_OBJECT(self));
2145}
2146
2147
2148static void
2149traceset_state_class_init (LttvTracesetContextClass *klass)
2150{
2151 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
2152
2153 gobject_class->finalize = (void (*)(GObject *self)) traceset_state_finalize;
2154 klass->init = (void (*)(LttvTracesetContext *self, LttvTraceset *ts))init;
2155 klass->fini = (void (*)(LttvTracesetContext *self))fini;
2156 klass->new_traceset_context = new_traceset_context;
2157 klass->new_trace_context = new_trace_context;
2158 klass->new_tracefile_context = new_tracefile_context;
2159}
2160
2161
2162GType
2163lttv_traceset_state_get_type(void)
2164{
2165 static GType type = 0;
2166 if (type == 0) {
2167 static const GTypeInfo info = {
2168 sizeof (LttvTracesetStateClass),
2169 NULL, /* base_init */
2170 NULL, /* base_finalize */
2171 (GClassInitFunc) traceset_state_class_init, /* class_init */
2172 NULL, /* class_finalize */
2173 NULL, /* class_data */
dbb7bb09 2174 sizeof (LttvTracesetState),
308711e5 2175 0, /* n_preallocs */
00e74b69 2176 (GInstanceInitFunc) traceset_state_instance_init, /* instance_init */
2177 NULL /* value handling */
308711e5 2178 };
2179
2180 type = g_type_register_static (LTTV_TRACESET_CONTEXT_TYPE, "LttvTracesetStateType",
2181 &info, 0);
2182 }
2183 return type;
2184}
2185
2186
2187static void
2188trace_state_instance_init (GTypeInstance *instance, gpointer g_class)
2189{
2190}
2191
2192
2193static void
2194trace_state_finalize (LttvTraceState *self)
2195{
2196 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_CONTEXT_TYPE))->
2197 finalize(G_OBJECT(self));
2198}
2199
2200
2201static void
2202trace_state_class_init (LttvTraceStateClass *klass)
2203{
2204 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
2205
2206 gobject_class->finalize = (void (*)(GObject *self)) trace_state_finalize;
2207 klass->state_save = state_save;
2208 klass->state_restore = state_restore;
2209 klass->state_saved_free = state_saved_free;
2210}
2211
2212
2213GType
2214lttv_trace_state_get_type(void)
2215{
2216 static GType type = 0;
2217 if (type == 0) {
2218 static const GTypeInfo info = {
2219 sizeof (LttvTraceStateClass),
2220 NULL, /* base_init */
2221 NULL, /* base_finalize */
2222 (GClassInitFunc) trace_state_class_init, /* class_init */
2223 NULL, /* class_finalize */
2224 NULL, /* class_data */
2225 sizeof (LttvTraceState),
2226 0, /* n_preallocs */
00e74b69 2227 (GInstanceInitFunc) trace_state_instance_init, /* instance_init */
2228 NULL /* value handling */
308711e5 2229 };
2230
2231 type = g_type_register_static (LTTV_TRACE_CONTEXT_TYPE,
2232 "LttvTraceStateType", &info, 0);
2233 }
2234 return type;
2235}
2236
2237
2238static void
2239tracefile_state_instance_init (GTypeInstance *instance, gpointer g_class)
2240{
2241}
2242
2243
2244static void
2245tracefile_state_finalize (LttvTracefileState *self)
2246{
2247 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_CONTEXT_TYPE))->
2248 finalize(G_OBJECT(self));
2249}
2250
2251
2252static void
2253tracefile_state_class_init (LttvTracefileStateClass *klass)
2254{
2255 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
2256
2257 gobject_class->finalize = (void (*)(GObject *self)) tracefile_state_finalize;
2258}
2259
2260
2261GType
2262lttv_tracefile_state_get_type(void)
2263{
2264 static GType type = 0;
2265 if (type == 0) {
2266 static const GTypeInfo info = {
2267 sizeof (LttvTracefileStateClass),
2268 NULL, /* base_init */
2269 NULL, /* base_finalize */
2270 (GClassInitFunc) tracefile_state_class_init, /* class_init */
2271 NULL, /* class_finalize */
2272 NULL, /* class_data */
2273 sizeof (LttvTracefileState),
2274 0, /* n_preallocs */
00e74b69 2275 (GInstanceInitFunc) tracefile_state_instance_init, /* instance_init */
2276 NULL /* value handling */
308711e5 2277 };
2278
2279 type = g_type_register_static (LTTV_TRACEFILE_CONTEXT_TYPE,
2280 "LttvTracefileStateType", &info, 0);
2281 }
2282 return type;
2283}
2284
2285
08b1c66e 2286static void module_init()
ffd54a90 2287{
2288 LTTV_STATE_UNNAMED = g_quark_from_string("unnamed");
b3fd4c02 2289 LTTV_STATE_MODE_UNKNOWN = g_quark_from_string("MODE_UNKNOWN");
2290 LTTV_STATE_USER_MODE = g_quark_from_string("USER_MODE");
2291 LTTV_STATE_SYSCALL = g_quark_from_string("SYSCALL");
2292 LTTV_STATE_TRAP = g_quark_from_string("TRAP");
2293 LTTV_STATE_IRQ = g_quark_from_string("IRQ");
2294 LTTV_STATE_SOFT_IRQ = g_quark_from_string("SOFTIRQ");
2295 LTTV_STATE_SUBMODE_UNKNOWN = g_quark_from_string("UNKNOWN");
2296 LTTV_STATE_SUBMODE_NONE = g_quark_from_string("NONE");
2297 LTTV_STATE_WAIT_FORK = g_quark_from_string("WAIT_FORK");
2298 LTTV_STATE_WAIT_CPU = g_quark_from_string("WAIT_CPU");
2299 LTTV_STATE_EXIT = g_quark_from_string("EXIT");
2300 LTTV_STATE_ZOMBIE = g_quark_from_string("ZOMBIE");
2301 LTTV_STATE_WAIT = g_quark_from_string("WAIT");
2302 LTTV_STATE_RUN = g_quark_from_string("RUN");
2303 LTTV_STATE_DEAD = g_quark_from_string("DEAD");
308711e5 2304 LTTV_STATE_TRACEFILES = g_quark_from_string("tracefiles");
2305 LTTV_STATE_PROCESSES = g_quark_from_string("processes");
2306 LTTV_STATE_PROCESS = g_quark_from_string("process");
348c6ba8 2307 LTTV_STATE_RUNNING_PROCESS = g_quark_from_string("running_process");
308711e5 2308 LTTV_STATE_EVENT = g_quark_from_string("event");
2309 LTTV_STATE_SAVED_STATES = g_quark_from_string("saved states");
dbb7bb09 2310 LTTV_STATE_SAVED_STATES_TIME = g_quark_from_string("saved states time");
308711e5 2311 LTTV_STATE_TIME = g_quark_from_string("time");
ffd54a90 2312 LTTV_STATE_HOOKS = g_quark_from_string("saved state hooks");
f95bc830 2313 LTTV_STATE_NAME_TABLES = g_quark_from_string("name tables");
2314 LTTV_STATE_TRACE_STATE_USE_COUNT =
2315 g_quark_from_string("trace_state_use_count");
eed2ef37 2316
2317
2318 LTT_FACILITY_KERNEL = g_quark_from_string("kernel");
f5d7967f 2319 LTT_FACILITY_KERNEL_ARCH = g_quark_from_string("kernel_arch");
eed2ef37 2320 LTT_FACILITY_PROCESS = g_quark_from_string("process");
f4b88a7d 2321 LTT_FACILITY_FS = g_quark_from_string("fs");
b3fd4c02 2322 LTT_FACILITY_STATEDUMP = g_quark_from_string("statedump");
eed2ef37 2323
2324
2325 LTT_EVENT_SYSCALL_ENTRY = g_quark_from_string("syscall_entry");
2326 LTT_EVENT_SYSCALL_EXIT = g_quark_from_string("syscall_exit");
2327 LTT_EVENT_TRAP_ENTRY = g_quark_from_string("trap_entry");
2328 LTT_EVENT_TRAP_EXIT = g_quark_from_string("trap_exit");
2329 LTT_EVENT_IRQ_ENTRY = g_quark_from_string("irq_entry");
2330 LTT_EVENT_IRQ_EXIT = g_quark_from_string("irq_exit");
faf074a3 2331 LTT_EVENT_SOFT_IRQ_ENTRY = g_quark_from_string("soft_irq_entry");
2332 LTT_EVENT_SOFT_IRQ_EXIT = g_quark_from_string("soft_irq_exit");
eed2ef37 2333 LTT_EVENT_SCHEDCHANGE = g_quark_from_string("schedchange");
2334 LTT_EVENT_FORK = g_quark_from_string("fork");
2335 LTT_EVENT_EXIT = g_quark_from_string("exit");
2336 LTT_EVENT_FREE = g_quark_from_string("free");
f4b88a7d 2337 LTT_EVENT_EXEC = g_quark_from_string("exec");
b3fd4c02 2338 LTT_EVENT_ENUM_PROCESS_STATE = g_quark_from_string("enumerate_process_state");
eed2ef37 2339
2340
2341 LTT_FIELD_SYSCALL_ID = g_quark_from_string("syscall_id");
2342 LTT_FIELD_TRAP_ID = g_quark_from_string("trap_id");
2343 LTT_FIELD_IRQ_ID = g_quark_from_string("irq_id");
faf074a3 2344 LTT_FIELD_SOFT_IRQ_ID = g_quark_from_string("softirq_id");
eed2ef37 2345 LTT_FIELD_OUT = g_quark_from_string("out");
2346 LTT_FIELD_IN = g_quark_from_string("in");
2347 LTT_FIELD_OUT_STATE = g_quark_from_string("out_state");
2348 LTT_FIELD_PARENT_PID = g_quark_from_string("parent_pid");
2349 LTT_FIELD_CHILD_PID = g_quark_from_string("child_pid");
2350 LTT_FIELD_PID = g_quark_from_string("pid");
f4b88a7d 2351 LTT_FIELD_FILENAME = g_quark_from_string("filename");
b3fd4c02 2352 LTT_FIELD_NAME = g_quark_from_string("name");
2353 LTT_FIELD_MODE = g_quark_from_string("mode");
2354 LTT_FIELD_SUBMODE = g_quark_from_string("submode");
2355 LTT_FIELD_STATUS = g_quark_from_string("status");
eed2ef37 2356
ffd54a90 2357}
dc877563 2358
08b1c66e 2359static void module_destroy()
ffd54a90 2360{
2361}
dc877563 2362
2363
08b1c66e 2364LTTV_MODULE("state", "State computation", \
2365 "Update the system state, possibly saving it at intervals", \
2366 module_init, module_destroy)
2367
dc877563 2368
2369
This page took 0.165424 seconds and 4 git commands to generate.