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