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