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