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