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