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