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