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