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