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