update print softirq
[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
2299 if(syscall < nb_syscalls) {
2300 submode = ((LttvTraceState *)(s->parent.t_context))->syscall_names[
2301 syscall];
2302 } else {
2303 /* Fixup an incomplete syscall table */
2304 GString *string = g_string_new("");
7cd289b0 2305 g_string_printf(string, "syscall %u", syscall);
80e0221b 2306 submode = g_quark_from_string(string->str);
2307 g_string_free(string, TRUE);
2308 }
1e304fa1 2309 /* There can be no system call from PID 0 : unknown state */
2310 if(process->pid != 0)
2311 push_state(s, LTTV_STATE_SYSCALL, submode);
dc877563 2312 return FALSE;
2313}
2314
2315
b445142a 2316static gboolean syscall_exit(void *hook_data, void *call_data)
dc877563 2317{
ba576a78 2318 LttvTracefileState *s = (LttvTracefileState *)call_data;
1e304fa1 2319 guint cpu = s->cpu;
2320 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
2321 LttvProcessState *process = ts->running_process[cpu];
dc877563 2322
1e304fa1 2323 /* There can be no system call from PID 0 : unknown state */
2324 if(process->pid != 0)
2325 pop_state(s, LTTV_STATE_SYSCALL);
dc877563 2326 return FALSE;
2327}
2328
2329
b445142a 2330static gboolean trap_entry(void *hook_data, void *call_data)
dc877563 2331{
ba576a78 2332 LttvTracefileState *s = (LttvTracefileState *)call_data;
a81d2a59 2333 LttvTraceState *ts = (LttvTraceState *)s->parent.t_context;
eed2ef37 2334 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
0ceef9de 2335 LttvTraceHook *th = (LttvTraceHook *)hook_data;
d3a66443 2336 struct marker_field *f = lttv_trace_get_hook_field(th, 0);
dc877563 2337
b445142a 2338 LttvExecutionSubmode submode;
2339
17ddd1f2 2340 guint64 nb_traps = ((LttvTraceState *)(s->parent.t_context))->nb_traps;
2341 guint64 trap = ltt_event_get_long_unsigned(e, f);
5e96e7e3 2342
2343 if(trap < nb_traps) {
2344 submode = ((LttvTraceState *)(s->parent.t_context))->trap_names[trap];
2345 } else {
2346 /* Fixup an incomplete trap table */
2347 GString *string = g_string_new("");
fcc08e1e 2348 g_string_printf(string, "trap %llu", trap);
5e96e7e3 2349 submode = g_quark_from_string(string->str);
2350 g_string_free(string, TRUE);
2351 }
2352
b445142a 2353 push_state(s, LTTV_STATE_TRAP, submode);
d3d99fde 2354
2355 /* update cpu status */
2356 cpu_push_mode(s->cpu_state, LTTV_CPU_TRAP);
2357
a81d2a59 2358 /* update trap status */
2359 s->cpu_state->last_trap = trap;
2360 ts->trap_states[trap].running++;
2361
dc877563 2362 return FALSE;
2363}
2364
b445142a 2365static gboolean trap_exit(void *hook_data, void *call_data)
dc877563 2366{
ba576a78 2367 LttvTracefileState *s = (LttvTracefileState *)call_data;
a81d2a59 2368 LttvTraceState *ts = (LttvTraceState *)s->parent.t_context;
2369 guint trap = s->cpu_state->last_trap;
dc877563 2370
ffd54a90 2371 pop_state(s, LTTV_STATE_TRAP);
d3d99fde 2372
2373 /* update cpu status */
2374 cpu_pop_mode(s->cpu_state);
2375
a81d2a59 2376 /* update trap status */
2377 if(ts->trap_states[trap].running)
2378 ts->trap_states[trap].running--;
2379
dc877563 2380 return FALSE;
2381}
2382
b445142a 2383static gboolean irq_entry(void *hook_data, void *call_data)
dc877563 2384{
ba576a78 2385 LttvTracefileState *s = (LttvTracefileState *)call_data;
5e563da0 2386 LttvTraceState *ts = (LttvTraceState *)s->parent.t_context;
eed2ef37 2387 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
0ceef9de 2388 //guint8 ev_id = ltt_event_eventtype_id(e);
2389 LttvTraceHook *th = (LttvTraceHook *)hook_data;
d3a66443 2390 struct marker_field *f = lttv_trace_get_hook_field(th, 0);
dc877563 2391
b445142a 2392 LttvExecutionSubmode submode;
1bb8d3a5 2393 guint64 irq = ltt_event_get_long_unsigned(e, f);
6214c229 2394 guint64 nb_irqs = ((LttvTraceState *)(s->parent.t_context))->nb_irqs;
b445142a 2395
6214c229 2396 if(irq < nb_irqs) {
2397 submode = ((LttvTraceState *)(s->parent.t_context))->irq_names[irq];
2398 } else {
2399 /* Fixup an incomplete irq table */
2400 GString *string = g_string_new("");
2401 g_string_printf(string, "irq %llu", irq);
2402 submode = g_quark_from_string(string->str);
2403 g_string_free(string, TRUE);
2404 }
b445142a 2405
dc877563 2406 /* Do something with the info about being in user or system mode when int? */
b445142a 2407 push_state(s, LTTV_STATE_IRQ, submode);
598026ba 2408
2409 /* update cpu status */
d3d99fde 2410 cpu_push_mode(s->cpu_state, LTTV_CPU_IRQ);
598026ba 2411
5e563da0 2412 /* update irq status */
8743690d 2413 s->cpu_state->last_irq = irq;
5e563da0 2414 irq_push_mode(&ts->irq_states[irq], LTTV_IRQ_BUSY);
2415
dc877563 2416 return FALSE;
2417}
2418
302efbad 2419static gboolean soft_irq_exit(void *hook_data, void *call_data)
2420{
2421 LttvTracefileState *s = (LttvTracefileState *)call_data;
0305fe77 2422 LttvTraceState *ts = (LttvTraceState *)s->parent.t_context;
2423 guint softirq = s->cpu_state->last_soft_irq;
302efbad 2424
2425 pop_state(s, LTTV_STATE_SOFT_IRQ);
302efbad 2426
0305fe77 2427 /* update softirq status */
2428 if(ts->soft_irq_states[softirq].running)
2429 ts->soft_irq_states[softirq].running--;
302efbad 2430
d34141ca 2431 /* update cpu status */
2432 cpu_pop_mode(s->cpu_state);
2433
0305fe77 2434 return FALSE;
2435}
dc877563 2436
b445142a 2437static gboolean irq_exit(void *hook_data, void *call_data)
dc877563 2438{
ba576a78 2439 LttvTracefileState *s = (LttvTracefileState *)call_data;
8743690d 2440 LttvTraceState *ts = (LttvTraceState *)s->parent.t_context;
dc877563 2441
ffd54a90 2442 pop_state(s, LTTV_STATE_IRQ);
598026ba 2443
2444 /* update cpu status */
d3d99fde 2445 cpu_pop_mode(s->cpu_state);
598026ba 2446
8743690d 2447 /* update irq status */
2448 irq_pop_mode(&ts->irq_states[s->cpu_state->last_irq]);
2449
dc877563 2450 return FALSE;
2451}
2452
faf074a3 2453static gboolean soft_irq_entry(void *hook_data, void *call_data)
2454{
2455 LttvTracefileState *s = (LttvTracefileState *)call_data;
0305fe77 2456 LttvTraceState *ts = (LttvTraceState *)s->parent.t_context;
faf074a3 2457 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
0ceef9de 2458 //guint8 ev_id = ltt_event_eventtype_id(e);
2459 LttvTraceHook *th = (LttvTraceHook *)hook_data;
d3a66443 2460 struct marker_field *f = lttv_trace_get_hook_field(th, 0);
faf074a3 2461
2462 LttvExecutionSubmode submode;
1bb8d3a5 2463 guint64 softirq = ltt_event_get_long_unsigned(e, f);
0305fe77 2464 guint64 nb_softirqs = ((LttvTraceState *)(s->parent.t_context))->nb_soft_irqs;
faf074a3 2465
6214c229 2466 if(softirq < nb_softirqs) {
2467 submode = ((LttvTraceState *)(s->parent.t_context))->soft_irq_names[softirq];
2468 } else {
2469 /* Fixup an incomplete irq table */
2470 GString *string = g_string_new("");
2471 g_string_printf(string, "softirq %llu", softirq);
2472 submode = g_quark_from_string(string->str);
2473 g_string_free(string, TRUE);
2474 }
faf074a3 2475
2476 /* Do something with the info about being in user or system mode when int? */
2477 push_state(s, LTTV_STATE_SOFT_IRQ, submode);
0305fe77 2478
d34141ca 2479 /* update cpu status */
2480 cpu_push_mode(s->cpu_state, LTTV_CPU_SOFT_IRQ);
2481
0305fe77 2482 /* update softirq status */
2483 s->cpu_state->last_soft_irq = softirq;
2484 ts->soft_irq_states[softirq].running++;
2485
faf074a3 2486 return FALSE;
2487}
2488
38b73700 2489static gboolean enum_interrupt(void *hook_data, void *call_data)
2490{
2491 LttvTracefileState *s = (LttvTracefileState *)call_data;
2492 LttvTraceState *ts = (LttvTraceState *)s->parent.t_context;
2493 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
0ceef9de 2494 //guint8 ev_id = ltt_event_eventtype_id(e);
2495 LttvTraceHook *th = (LttvTraceHook *)hook_data;
38b73700 2496
d3a66443 2497 GQuark action = g_quark_from_string(ltt_event_get_string(e,
2498 lttv_trace_get_hook_field(th, 0)));
2499 guint irq = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 1));
38b73700 2500
2501 ts->irq_names[irq] = action;
2502
2503 return FALSE;
2504}
2505
2506
27811799 2507static gboolean bdev_request_issue(void *hook_data, void *call_data)
2508{
2509 LttvTracefileState *s = (LttvTracefileState *)call_data;
2510 LttvTraceState *ts = (LttvTraceState *)s->parent.t_context;
2511 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
0ceef9de 2512 //guint8 ev_id = ltt_event_eventtype_id(e);
2513 LttvTraceHook *th = (LttvTraceHook *)hook_data;
27811799 2514
d3a66443 2515 guint major = ltt_event_get_long_unsigned(e,
2516 lttv_trace_get_hook_field(th, 0));
2517 guint minor = ltt_event_get_long_unsigned(e,
2518 lttv_trace_get_hook_field(th, 1));
2519 guint oper = ltt_event_get_long_unsigned(e,
2520 lttv_trace_get_hook_field(th, 2));
27811799 2521 guint16 devcode = MKDEV(major,minor);
2522
2523 /* have we seen this block device before? */
98d7814f 2524 gpointer bdev = get_hashed_bdevstate(ts, devcode);
27811799 2525
2526 if(oper == 0)
2527 bdev_push_mode(bdev, LTTV_BDEV_BUSY_READING);
2528 else
2529 bdev_push_mode(bdev, LTTV_BDEV_BUSY_WRITING);
2530
2531 return FALSE;
2532}
2533
2534static gboolean bdev_request_complete(void *hook_data, void *call_data)
2535{
2536 LttvTracefileState *s = (LttvTracefileState *)call_data;
2537 LttvTraceState *ts = (LttvTraceState *)s->parent.t_context;
2538 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
0ceef9de 2539 LttvTraceHook *th = (LttvTraceHook *)hook_data;
27811799 2540
d3a66443 2541 guint major = ltt_event_get_long_unsigned(e,
2542 lttv_trace_get_hook_field(th, 0));
2543 guint minor = ltt_event_get_long_unsigned(e,
2544 lttv_trace_get_hook_field(th, 1));
2545 //guint oper = ltt_event_get_long_unsigned(e,
2546 // lttv_trace_get_hook_field(th, 2));
27811799 2547 guint16 devcode = MKDEV(major,minor);
2548
2549 /* have we seen this block device before? */
98d7814f 2550 gpointer bdev = get_hashed_bdevstate(ts, devcode);
27811799 2551
2552 /* update block device */
2553 bdev_pop_mode(bdev);
2554
2555 return FALSE;
2556}
2557
302efbad 2558static void push_function(LttvTracefileState *tfs, guint64 funcptr)
2559{
2560 guint64 *new_func;
2561
2562 LttvTraceState *ts = (LttvTraceState*)tfs->parent.t_context;
2563 guint cpu = tfs->cpu;
2564 LttvProcessState *process = ts->running_process[cpu];
faf074a3 2565
302efbad 2566 guint depth = process->user_stack->len;
2567
d3a66443 2568 process->user_stack =
302efbad 2569 g_array_set_size(process->user_stack, depth + 1);
2570
2571 new_func = &g_array_index(process->user_stack, guint64, depth);
80e0221b 2572 *new_func = funcptr;
9bff13df 2573 process->current_function = funcptr;
302efbad 2574}
2575
2576static void pop_function(LttvTracefileState *tfs, guint64 funcptr)
2577{
2578 guint cpu = tfs->cpu;
2579 LttvTraceState *ts = (LttvTraceState*)tfs->parent.t_context;
2580 LttvProcessState *process = ts->running_process[cpu];
2581
302efbad 2582 if(process->current_function != funcptr){
2583 g_info("Different functions (%lu.%09lu): ignore it\n",
2584 tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec);
2585 g_info("process state has %llu when pop_function is %llu\n",
80e0221b 2586 process->current_function, funcptr);
7b5f6cf1 2587 g_info("{ %u, %u, %s, %s, %s }\n",
80e0221b 2588 process->pid,
2589 process->ppid,
2590 g_quark_to_string(process->name),
2591 g_quark_to_string(process->brand),
2592 g_quark_to_string(process->state->s));
302efbad 2593 return;
2594 }
9bff13df 2595 guint depth = process->user_stack->len;
302efbad 2596
2597 if(depth == 0){
2598 g_info("Trying to pop last function on stack (%lu.%09lu): ignore it\n",
2599 tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec);
2600 return;
2601 }
2602
2603 process->user_stack =
2604 g_array_set_size(process->user_stack, depth - 1);
2605 process->current_function =
80e0221b 2606 g_array_index(process->user_stack, guint64, depth - 2);
302efbad 2607}
2608
2609
2610static gboolean function_entry(void *hook_data, void *call_data)
faf074a3 2611{
2612 LttvTracefileState *s = (LttvTracefileState *)call_data;
302efbad 2613 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
0ceef9de 2614 //guint8 ev_id = ltt_event_eventtype_id(e);
2615 LttvTraceHook *th = (LttvTraceHook *)hook_data;
d3a66443 2616 struct marker_field *f = lttv_trace_get_hook_field(th, 0);
80e0221b 2617 guint64 funcptr = ltt_event_get_long_unsigned(e, f);
faf074a3 2618
302efbad 2619 push_function(s, funcptr);
faf074a3 2620 return FALSE;
2621}
2622
302efbad 2623static gboolean function_exit(void *hook_data, void *call_data)
2624{
2625 LttvTracefileState *s = (LttvTracefileState *)call_data;
2626 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
0ceef9de 2627 //guint8 ev_id = ltt_event_eventtype_id(e);
2628 LttvTraceHook *th = (LttvTraceHook *)hook_data;
d3a66443 2629 struct marker_field *f = lttv_trace_get_hook_field(th, 0);
80e0221b 2630 guint64 funcptr = ltt_event_get_long_unsigned(e, f);
302efbad 2631
302efbad 2632 pop_function(s, funcptr);
2633 return FALSE;
2634}
dc877563 2635
cf453ac7 2636static gboolean dump_syscall(void *hook_data, void *call_data)
2637{
2638 LttvTracefileState *s = (LttvTracefileState *)call_data;
2639 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
2640 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
2641 LttvTraceHook *th = (LttvTraceHook *)hook_data;
2642 guint id;
2643 guint64 address;
2644 char *symbol;
2645
2646 id = ltt_event_get_unsigned(e, lttv_trace_get_hook_field(th, 0));
2647 address = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 1));
2648 symbol = ltt_event_get_string(e, lttv_trace_get_hook_field(th, 2));
2649
2650 if (ts->nb_syscalls < id) {
2651 GQuark *old_names = ts->syscall_names;
2652 guint new_nb_syscalls = max(id + 1, ts->nb_syscalls * 2);
2653 guint i;
2654 GString *fe_name = g_string_new("");
2655 ts->syscall_names = g_new(GQuark, new_nb_syscalls);
2656 memcpy(ts->syscall_names, old_names,
2657 ts->nb_syscalls * sizeof(GQuark));
2658 for(i = ts->nb_syscalls ; i < new_nb_syscalls ; i++) {
2659 g_string_printf(fe_name, "syscall %d", i);
2660 ts->syscall_names[i] = g_quark_from_string(fe_name->str);
2661 }
2662 g_string_free(fe_name, TRUE);
2663 ts->nb_syscalls = new_nb_syscalls;
2664 }
2665 ts->syscall_names[id] = g_quark_from_string(symbol);
2666
2667 return FALSE;
2668}
2669
dc6b2467 2670static gboolean dump_softirq(void *hook_data, void *call_data)
2671{
2672 LttvTracefileState *s = (LttvTracefileState *)call_data;
2673 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
2674 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
2675 LttvTraceHook *th = (LttvTraceHook *)hook_data;
2676 guint id;
2677 guint64 address;
2678 char *symbol;
2679
2680 id = ltt_event_get_unsigned(e, lttv_trace_get_hook_field(th, 0));
2681 address = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 1));
2682 symbol = ltt_event_get_string(e, lttv_trace_get_hook_field(th, 2));
2683 ts->soft_irq_names[id] = g_quark_from_string(symbol);
2684
2685 return FALSE;
2686}
2687
b445142a 2688static gboolean schedchange(void *hook_data, void *call_data)
dc877563 2689{
ba576a78 2690 LttvTracefileState *s = (LttvTracefileState *)call_data;
ae3d0f50 2691 guint cpu = s->cpu;
348c6ba8 2692 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
2693 LttvProcessState *process = ts->running_process[cpu];
5fd4c7a2 2694 //LttvProcessState *old_process = ts->running_process[cpu];
348c6ba8 2695
eed2ef37 2696 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
0ceef9de 2697 LttvTraceHook *th = (LttvTraceHook *)hook_data;
73394fd3 2698 guint pid_in, pid_out;
7092fb86 2699 gint64 state_out;
dc877563 2700
d3a66443 2701 pid_out = ltt_event_get_unsigned(e, lttv_trace_get_hook_field(th, 0));
2702 pid_in = ltt_event_get_unsigned(e, lttv_trace_get_hook_field(th, 1));
2703 state_out = ltt_event_get_long_int(e, lttv_trace_get_hook_field(th, 2));
348c6ba8 2704
2705 if(likely(process != NULL)) {
b445142a 2706
f95bc830 2707 /* We could not know but it was not the idle process executing.
2708 This should only happen at the beginning, before the first schedule
2709 event, and when the initial information (current process for each CPU)
2710 is missing. It is not obvious how we could, after the fact, compensate
2711 the wrongly attributed statistics. */
2712
240f1fea 2713 //This test only makes sense once the state is known and if there is no
48b002b8 2714 //missing events. We need to silently ignore schedchange coming after a
80e0221b 2715 //process_free, or it causes glitches. (FIXME)
348c6ba8 2716 //if(unlikely(process->pid != pid_out)) {
2717 // g_assert(process->pid == 0);
240f1fea 2718 //}
c4a72569 2719 if(process->pid == 0
2720 && process->state->t == LTTV_STATE_MODE_UNKNOWN) {
2721 if(pid_out == 0) {
2722 /* Scheduling out of pid 0 at beginning of the trace :
2723 * we know for sure it is in syscall mode at this point. */
2724 g_assert(process->execution_stack->len == 1);
2725 process->state->t = LTTV_STATE_SYSCALL;
2726 process->state->s = LTTV_STATE_WAIT;
2727 process->state->change = s->parent.timestamp;
d3670e3d 2728 process->state->entry = s->parent.timestamp;
c4a72569 2729 }
dbd243b1 2730 } else {
c4a72569 2731 if(unlikely(process->state->s == LTTV_STATE_EXIT)) {
2732 process->state->s = LTTV_STATE_ZOMBIE;
2733 process->state->change = s->parent.timestamp;
2734 } else {
2735 if(unlikely(state_out == 0)) process->state->s = LTTV_STATE_WAIT_CPU;
2736 else process->state->s = LTTV_STATE_WAIT;
2737 process->state->change = s->parent.timestamp;
2738 }
2739
c7620c79 2740 if(state_out == 32 || state_out == 64) { /* EXIT_DEAD || TASK_DEAD */
2741 /* see sched.h for states */
2fe13145 2742 if (!exit_process(s, process)) {
2743 process->state->s = LTTV_STATE_DEAD;
2744 process->state->change = s->parent.timestamp;
2745 }
c7620c79 2746 }
791dffa6 2747 }
dc877563 2748 }
348c6ba8 2749 process = ts->running_process[cpu] =
2750 lttv_state_find_process_or_create(
2751 (LttvTraceState*)s->parent.t_context,
2752 cpu, pid_in,
2753 &s->parent.timestamp);
2754 process->state->s = LTTV_STATE_RUN;
2755 process->cpu = cpu;
80e0221b 2756 if(process->usertrace)
2757 process->usertrace->cpu = cpu;
348c6ba8 2758 // process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)s)->tf);
2759 process->state->change = s->parent.timestamp;
44ffb95f 2760
2761 /* update cpu status */
2762 if(pid_in == 0)
14c7af39 2763 /* going to idle task */
d3d99fde 2764 cpu_set_base_mode(s->cpu_state, LTTV_CPU_IDLE);
14c7af39 2765 else {
2766 /* scheduling a real task.
2767 * we must be careful here:
2768 * if we just schedule()'ed to a process that is
2769 * in a trap, we must put the cpu in trap mode
2770 */
d3d99fde 2771 cpu_set_base_mode(s->cpu_state, LTTV_CPU_BUSY);
14c7af39 2772 if(process->state->t == LTTV_STATE_TRAP)
2773 cpu_push_mode(s->cpu_state, LTTV_CPU_TRAP);
2774 }
44ffb95f 2775
dc877563 2776 return FALSE;
2777}
2778
eed2ef37 2779static gboolean process_fork(void *hook_data, void *call_data)
dc877563 2780{
eed2ef37 2781 LttvTracefileState *s = (LttvTracefileState *)call_data;
2782 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
0ceef9de 2783 LttvTraceHook *th = (LttvTraceHook *)hook_data;
eed2ef37 2784 guint parent_pid;
fcc08e1e 2785 guint child_pid; /* In the Linux Kernel, there is one PID per thread. */
2786 guint child_tgid; /* tgid in the Linux kernel is the "real" POSIX PID. */
0ceef9de 2787 //LttvProcessState *zombie_process;
ae3d0f50 2788 guint cpu = s->cpu;
348c6ba8 2789 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
2790 LttvProcessState *process = ts->running_process[cpu];
26275aa2 2791 LttvProcessState *child_process;
d3a66443 2792 struct marker_field *f;
2cdc690b 2793
eed2ef37 2794 /* Parent PID */
d3a66443 2795 parent_pid = ltt_event_get_unsigned(e, lttv_trace_get_hook_field(th, 0));
eed2ef37 2796
2cdc690b 2797 /* Child PID */
d3a66443 2798 child_pid = ltt_event_get_unsigned(e, lttv_trace_get_hook_field(th, 1));
33bdc8dd 2799 s->parent.target_pid = child_pid;
2cdc690b 2800
fcc08e1e 2801 /* Child TGID */
d3a66443 2802 f = lttv_trace_get_hook_field(th, 2);
2803 if (likely(f))
2804 child_tgid = ltt_event_get_unsigned(e, f);
2805 else
2806 child_tgid = 0;
fcc08e1e 2807
15b3d537 2808 /* Mathieu : it seems like the process might have been scheduled in before the
2809 * fork, and, in a rare case, might be the current process. This might happen
d4942a23 2810 * in a SMP case where we don't have enough precision on the clocks.
2811 *
2812 * Test reenabled after precision fixes on time. (Mathieu) */
791dffa6 2813#if 0
348c6ba8 2814 zombie_process = lttv_state_find_process(ts, ANY_CPU, child_pid);
dc877563 2815
1d1df11d 2816 if(unlikely(zombie_process != NULL)) {
4ad73431 2817 /* Reutilisation of PID. Only now we are sure that the old PID
eed2ef37 2818 * has been released. FIXME : should know when release_task happens instead.
4ad73431 2819 */
15b3d537 2820 guint num_cpus = ltt_trace_get_num_cpu(ts->parent.t);
2821 guint i;
2822 for(i=0; i< num_cpus; i++) {
5ac05980 2823 g_assert(zombie_process != ts->running_process[i]);
15b3d537 2824 }
2825
4ad73431 2826 exit_process(s, zombie_process);
2827 }
791dffa6 2828#endif //0
348c6ba8 2829 g_assert(process->pid != child_pid);
eed2ef37 2830 // FIXME : Add this test in the "known state" section
348c6ba8 2831 // g_assert(process->pid == parent_pid);
26275aa2 2832 child_process = lttv_state_find_process(ts, ANY_CPU, child_pid);
2833 if(child_process == NULL) {
ab893fb1 2834 child_process = lttv_state_create_process(ts, process, cpu,
fcc08e1e 2835 child_pid, child_tgid,
2836 LTTV_STATE_UNNAMED, &s->parent.timestamp);
26275aa2 2837 } else {
2838 /* The process has already been created : due to time imprecision between
791dffa6 2839 * multiple CPUs : it has been scheduled in before creation. Note that we
2840 * shouldn't have this kind of imprecision.
26275aa2 2841 *
2842 * Simply put a correct parent.
2843 */
e4d45514 2844 g_error("Process %u has been created before fork on cpu %u. Probably an unsynchronized TSC problem on the traced machine.", child_pid, cpu);
2845 //g_assert(0); /* This is a problematic case : the process has been created
2846 // before the fork event */
26275aa2 2847 child_process->ppid = process->pid;
fcc08e1e 2848 child_process->tgid = child_tgid;
26275aa2 2849 }
0292757b 2850 g_assert(child_process->name == LTTV_STATE_UNNAMED);
2851 child_process->name = process->name;
2852 child_process->brand = process->brand;
4ad73431 2853
dc877563 2854 return FALSE;
2855}
2856
89f8741a 2857/* We stamp a newly created process as kernel_thread.
2858 * The thread should not be running yet. */
7bfd7820 2859static gboolean process_kernel_thread(void *hook_data, void *call_data)
2860{
2861 LttvTracefileState *s = (LttvTracefileState *)call_data;
2862 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
0ceef9de 2863 LttvTraceHook *th = (LttvTraceHook *)hook_data;
7bfd7820 2864 guint pid;
7bfd7820 2865 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
2866 LttvProcessState *process;
2867 LttvExecutionState *es;
2868
2869 /* PID */
d3a66443 2870 pid = (guint)ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 0));
33bdc8dd 2871 s->parent.target_pid = pid;
7bfd7820 2872
61c8808e 2873 process = lttv_state_find_process_or_create(ts, ANY_CPU, pid,
2874 &ltt_time_zero);
c7620c79 2875 if (process->state->s != LTTV_STATE_DEAD) {
2876 process->execution_stack =
2877 g_array_set_size(process->execution_stack, 1);
2878 es = process->state =
2879 &g_array_index(process->execution_stack, LttvExecutionState, 0);
2880 es->t = LTTV_STATE_SYSCALL;
2881 }
80e0221b 2882 process->type = LTTV_STATE_KERNEL_THREAD;
7bfd7820 2883
80e0221b 2884 return FALSE;
7bfd7820 2885}
dc877563 2886
eed2ef37 2887static gboolean process_exit(void *hook_data, void *call_data)
dc877563 2888{
eed2ef37 2889 LttvTracefileState *s = (LttvTracefileState *)call_data;
2890 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
0ceef9de 2891 LttvTraceHook *th = (LttvTraceHook *)hook_data;
eed2ef37 2892 guint pid;
348c6ba8 2893 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
6f54e0f4 2894 LttvProcessState *process; // = ts->running_process[cpu];
eed2ef37 2895
d3a66443 2896 pid = ltt_event_get_unsigned(e, lttv_trace_get_hook_field(th, 0));
33bdc8dd 2897 s->parent.target_pid = pid;
eed2ef37 2898
2899 // FIXME : Add this test in the "known state" section
348c6ba8 2900 // g_assert(process->pid == pid);
eed2ef37 2901
6f54e0f4 2902 process = lttv_state_find_process(ts, ANY_CPU, pid);
348c6ba8 2903 if(likely(process != NULL)) {
2904 process->state->s = LTTV_STATE_EXIT;
2cdc690b 2905 }
2906 return FALSE;
2cdc690b 2907}
2908
eed2ef37 2909static gboolean process_free(void *hook_data, void *call_data)
2da61677 2910{
eed2ef37 2911 LttvTracefileState *s = (LttvTracefileState *)call_data;
348c6ba8 2912 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
eed2ef37 2913 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
0ceef9de 2914 LttvTraceHook *th = (LttvTraceHook *)hook_data;
2da61677 2915 guint release_pid;
2916 LttvProcessState *process;
2917
2918 /* PID of the process to release */
d3a66443 2919 release_pid = ltt_event_get_unsigned(e, lttv_trace_get_hook_field(th, 0));
33bdc8dd 2920 s->parent.target_pid = release_pid;
15b3d537 2921
2922 g_assert(release_pid != 0);
2da61677 2923
348c6ba8 2924 process = lttv_state_find_process(ts, ANY_CPU, release_pid);
c7620c79 2925 if(likely(process != NULL))
2926 exit_process(s, process);
2fe13145 2927 return FALSE;
2928//DISABLED
2929 if(likely(process != NULL)) {
2930 /* release_task is happening at kernel level : we can now safely release
2931 * the data structure of the process */
2932 //This test is fun, though, as it may happen that
2933 //at time t : CPU 0 : process_free
2934 //at time t+150ns : CPU 1 : schedule out
2935 //Clearly due to time imprecision, we disable it. (Mathieu)
2936 //If this weird case happen, we have no choice but to put the
2937 //Currently running process on the cpu to 0.
2938 //I re-enable it following time precision fixes. (Mathieu)
2939 //Well, in the case where an process is freed by a process on another CPU
2940 //and still scheduled, it happens that this is the schedchange that will
2941 //drop the last reference count. Do not free it here!
2942 guint num_cpus = ltt_trace_get_num_cpu(ts->parent.t);
2943 guint i;
2944 for(i=0; i< num_cpus; i++) {
2945 //g_assert(process != ts->running_process[i]);
2946 if(process == ts->running_process[i]) {
2947 //ts->running_process[i] = lttv_state_find_process(ts, i, 0);
2948 break;
2949 }
2950 }
2951 if(i == num_cpus) /* process is not scheduled */
2952 exit_process(s, process);
2953 }
2da61677 2954
2955 return FALSE;
2956}
2957
f4b88a7d 2958
2959static gboolean process_exec(void *hook_data, void *call_data)
2960{
2961 LttvTracefileState *s = (LttvTracefileState *)call_data;
2962 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
2963 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
0ceef9de 2964 LttvTraceHook *th = (LttvTraceHook *)hook_data;
743e50fd 2965 //gchar *name;
ae3d0f50 2966 guint cpu = s->cpu;
f4b88a7d 2967 LttvProcessState *process = ts->running_process[cpu];
2968
f63ebe51 2969#if 0//how to use a sequence that must be transformed in a string
f4b88a7d 2970 /* PID of the process to release */
d3a66443 2971 guint64 name_len = ltt_event_field_element_number(e,
2972 lttv_trace_get_hook_field(th, 0));
2973 //name = ltt_event_get_string(e, lttv_trace_get_hook_field(th, 0));
2974 LttField *child = ltt_event_field_element_select(e,
2975 lttv_trace_get_hook_field(th, 0), 0);
f2923fb2 2976 gchar *name_begin =
2977 (gchar*)(ltt_event_data(e)+ltt_event_field_offset(e, child));
743e50fd 2978 gchar *null_term_name = g_new(gchar, name_len+1);
2979 memcpy(null_term_name, name_begin, name_len);
2980 null_term_name[name_len] = '\0';
743e50fd 2981 process->name = g_quark_from_string(null_term_name);
f63ebe51 2982#endif //0
2983
d3a66443 2984 process->name = g_quark_from_string(ltt_event_get_string(e,
2985 lttv_trace_get_hook_field(th, 0)));
0292757b 2986 process->brand = LTTV_STATE_UNBRANDED;
f63ebe51 2987 //g_free(null_term_name);
f4b88a7d 2988 return FALSE;
2989}
2990
7b5f6cf1 2991static gboolean thread_brand(void *hook_data, void *call_data)
2992{
2993 LttvTracefileState *s = (LttvTracefileState *)call_data;
2994 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
2995 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
0ceef9de 2996 LttvTraceHook *th = (LttvTraceHook *)hook_data;
7b5f6cf1 2997 gchar *name;
2998 guint cpu = s->cpu;
2999 LttvProcessState *process = ts->running_process[cpu];
3000
d3a66443 3001 name = ltt_event_get_string(e, lttv_trace_get_hook_field(th, 0));
7b5f6cf1 3002 process->brand = g_quark_from_string(name);
3003
3004 return FALSE;
3005}
3006
c3b3b60b 3007static void fix_process(gpointer key, gpointer value,
3008 gpointer user_data)
3009{
3010 LttvProcessState *process;
3011 LttvExecutionState *es;
3012 process = (LttvProcessState *)value;
c3b3b60b 3013 LttTime *timestamp = (LttTime*)user_data;
3014
c3b3b60b 3015 if(process->type == LTTV_STATE_KERNEL_THREAD) {
2b25224d 3016 es = &g_array_index(process->execution_stack, LttvExecutionState, 0);
3017 if(es->t == LTTV_STATE_MODE_UNKNOWN) {
3018 es->t = LTTV_STATE_SYSCALL;
2b25224d 3019 es->n = LTTV_STATE_SUBMODE_NONE;
3020 es->entry = *timestamp;
3021 es->change = *timestamp;
3022 es->cum_cpu_time = ltt_time_zero;
c4a72569 3023 if(es->s == LTTV_STATE_UNNAMED)
3024 es->s = LTTV_STATE_WAIT;
c3b3b60b 3025 }
3026 } else {
2b25224d 3027 es = &g_array_index(process->execution_stack, LttvExecutionState, 0);
3028 if(es->t == LTTV_STATE_MODE_UNKNOWN) {
c3b3b60b 3029 es->t = LTTV_STATE_USER_MODE;
3030 es->n = LTTV_STATE_SUBMODE_NONE;
3031 es->entry = *timestamp;
3032 //g_assert(timestamp->tv_sec != 0);
3033 es->change = *timestamp;
3034 es->cum_cpu_time = ltt_time_zero;
c4a72569 3035 if(es->s == LTTV_STATE_UNNAMED)
3036 es->s = LTTV_STATE_RUN;
c3b3b60b 3037
2b25224d 3038 if(process->execution_stack->len == 1) {
89f8741a 3039 /* Still in bottom unknown mode, means never did a system call
3040 * May be either in user mode, syscall mode, running or waiting.*/
3041 /* FIXME : we may be tagging syscall mode when being user mode */
2b25224d 3042 process->execution_stack =
3043 g_array_set_size(process->execution_stack, 2);
3044 es = process->state = &g_array_index(process->execution_stack,
c3b3b60b 3045 LttvExecutionState, 1);
2b25224d 3046 es->t = LTTV_STATE_SYSCALL;
3047 es->n = LTTV_STATE_SUBMODE_NONE;
3048 es->entry = *timestamp;
3049 //g_assert(timestamp->tv_sec != 0);
3050 es->change = *timestamp;
3051 es->cum_cpu_time = ltt_time_zero;
b59b7222 3052 if(es->s == LTTV_STATE_WAIT_FORK)
3053 es->s = LTTV_STATE_WAIT;
2b25224d 3054 }
c3b3b60b 3055 }
3056 }
3057}
3058
3059static gboolean statedump_end(void *hook_data, void *call_data)
3060{
3061 LttvTracefileState *s = (LttvTracefileState *)call_data;
3062 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
3063 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
0ceef9de 3064 //LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
3065 //LttvTraceHook *th = (LttvTraceHook *)hook_data;
c3b3b60b 3066
3067 /* For all processes */
3068 /* if kernel thread, if stack[0] is unknown, set to syscall mode, wait */
3069 /* else, if stack[0] is unknown, set to user mode, running */
3070
3071 g_hash_table_foreach(ts->processes, fix_process, &tfc->timestamp);
0ceef9de 3072
3073 return FALSE;
c3b3b60b 3074}
3075
b3fd4c02 3076static gboolean enum_process_state(void *hook_data, void *call_data)
3077{
3078 LttvTracefileState *s = (LttvTracefileState *)call_data;
3079 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
80e0221b 3080 //It's slow : optimise later by doing this before reading trace.
0ceef9de 3081 LttvTraceHook *th = (LttvTraceHook *)hook_data;
b3fd4c02 3082 guint parent_pid;
3083 guint pid;
fcc08e1e 3084 guint tgid;
b3fd4c02 3085 gchar * command;
ae3d0f50 3086 guint cpu = s->cpu;
b3fd4c02 3087 LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
3088 LttvProcessState *process = ts->running_process[cpu];
3089 LttvProcessState *parent_process;
d3a66443 3090 struct marker_field *f;
80e0221b 3091 GQuark type, mode, submode, status;
3092 LttvExecutionState *es;
c4a72569 3093 guint i, nb_cpus;
f4b88a7d 3094
b3fd4c02 3095 /* PID */
d3a66443 3096 pid = ltt_event_get_unsigned(e, lttv_trace_get_hook_field(th, 0));
e38d9ea0 3097 s->parent.target_pid = pid;
3098
b3fd4c02 3099 /* Parent PID */
d3a66443 3100 parent_pid = ltt_event_get_unsigned(e, lttv_trace_get_hook_field(th, 1));
b3fd4c02 3101
3102 /* Command name */
d3a66443 3103 command = ltt_event_get_string(e, lttv_trace_get_hook_field(th, 2));
b3fd4c02 3104
80e0221b 3105 /* type */
d3a66443 3106 f = lttv_trace_get_hook_field(th, 3);
deb8b4b2 3107 type = ltt_enum_string_get(f, ltt_event_get_unsigned(e, f));
b3fd4c02 3108
b0b1c1dd 3109 //FIXME: type is rarely used, enum must match possible types.
3110
80e0221b 3111 /* mode */
d3a66443 3112 f = lttv_trace_get_hook_field(th, 4);
deb8b4b2 3113 mode = ltt_enum_string_get(f,ltt_event_get_unsigned(e, f));
b3fd4c02 3114
80e0221b 3115 /* submode */
d3a66443 3116 f = lttv_trace_get_hook_field(th, 5);
deb8b4b2 3117 submode = ltt_enum_string_get(f, ltt_event_get_unsigned(e, f));
b3fd4c02 3118
80e0221b 3119 /* status */
d3a66443 3120 f = lttv_trace_get_hook_field(th, 6);
deb8b4b2 3121 status = ltt_enum_string_get(f, ltt_event_get_unsigned(e, f));
e62e7f3a 3122
fcc08e1e 3123 /* TGID */
d3a66443 3124 f = lttv_trace_get_hook_field(th, 7);
3125 if(f)
3126 tgid = ltt_event_get_unsigned(e, f);
3127 else
3128 tgid = 0;
c4a72569 3129
3130 if(pid == 0) {
3131 nb_cpus = ltt_trace_get_num_cpu(ts->parent.t);
3132 for(i=0; i<nb_cpus; i++) {
3133 process = lttv_state_find_process(ts, i, pid);
3134 g_assert(process != NULL);
3135
3136 process->ppid = parent_pid;
3137 process->tgid = tgid;
3138 process->name = g_quark_from_string(command);
3139 es =
3140 &g_array_index(process->execution_stack, LttvExecutionState, 0);
c3b3b60b 3141 process->type = LTTV_STATE_KERNEL_THREAD;
c4a72569 3142 }
3143
3144 } else {
3145 /* The process might exist if a process was forked while performing the
3146 * state dump. */
3147 process = lttv_state_find_process(ts, ANY_CPU, pid);
3148 if(process == NULL) {
3149 parent_process = lttv_state_find_process(ts, ANY_CPU, parent_pid);
3150 process = lttv_state_create_process(ts, parent_process, cpu,
3151 pid, tgid, g_quark_from_string(command),
3152 &s->parent.timestamp);
3153
3154 /* Keep the stack bottom : a running user mode */
3155 /* Disabled because of inconsistencies in the current statedump states. */
3156 if(type == LTTV_STATE_KERNEL_THREAD) {
3157 /* Only keep the bottom
3158 * FIXME Kernel thread : can be in syscall or interrupt or trap. */
3159 /* Will cause expected trap when in fact being syscall (even after end of
3160 * statedump event)
3161 * Will cause expected interrupt when being syscall. (only before end of
3162 * statedump event) */
3163 // This will cause a "popping last state on stack, ignoring it."
3164 process->execution_stack = g_array_set_size(process->execution_stack, 1);
3165 es = process->state = &g_array_index(process->execution_stack,
3166 LttvExecutionState, 0);
3167 process->type = LTTV_STATE_KERNEL_THREAD;
3168 es->t = LTTV_STATE_MODE_UNKNOWN;
3169 es->s = LTTV_STATE_UNNAMED;
3170 es->n = LTTV_STATE_SUBMODE_UNKNOWN;
3171 #if 0
3172 es->t = LTTV_STATE_SYSCALL;
3173 es->s = status;
3174 es->n = submode;
3175 #endif //0
3176 } else {
3177 /* User space process :
3178 * bottom : user mode
3179 * either currently running or scheduled out.
3180 * can be scheduled out because interrupted in (user mode or in syscall)
3181 * or because of an explicit call to the scheduler in syscall. Note that
3182 * the scheduler call comes after the irq_exit, so never in interrupt
3183 * context. */
3184 // temp workaround : set size to 1 : only have user mode bottom of stack.
3185 // will cause g_info message of expected syscall mode when in fact being
3186 // in user mode. Can also cause expected trap when in fact being user
3187 // mode in the event of a page fault reenabling interrupts in the handler.
3188 // Expected syscall and trap can also happen after the end of statedump
3189 // This will cause a "popping last state on stack, ignoring it."
3190 process->execution_stack = g_array_set_size(process->execution_stack, 1);
3191 es = process->state = &g_array_index(process->execution_stack,
3192 LttvExecutionState, 0);
3193 es->t = LTTV_STATE_MODE_UNKNOWN;
3194 es->s = LTTV_STATE_UNNAMED;
3195 es->n = LTTV_STATE_SUBMODE_UNKNOWN;
3196 #if 0
3197 es->t = LTTV_STATE_USER_MODE;
3198 es->s = status;
3199 es->n = submode;
3200 #endif //0
3201 }
3202 #if 0
3203 /* UNKNOWN STATE */
3204 {
3205 es = process->state = &g_array_index(process->execution_stack,
3206 LttvExecutionState, 1);
3207 es->t = LTTV_STATE_MODE_UNKNOWN;
3208 es->s = LTTV_STATE_UNNAMED;
3209 es->n = LTTV_STATE_SUBMODE_UNKNOWN;
3210 }
3211 #endif //0
80e0221b 3212 } else {
c4a72569 3213 /* The process has already been created :
3214 * Probably was forked while dumping the process state or
3215 * was simply scheduled in prior to get the state dump event.
3216 */
3217 process->ppid = parent_pid;
3218 process->tgid = tgid;
3219 process->name = g_quark_from_string(command);
3220 process->type = type;
3221 es =
3222 &g_array_index(process->execution_stack, LttvExecutionState, 0);
c3b3b60b 3223#if 0
c4a72569 3224 if(es->t == LTTV_STATE_MODE_UNKNOWN) {
3225 if(type == LTTV_STATE_KERNEL_THREAD)
3226 es->t = LTTV_STATE_SYSCALL;
3227 else
3228 es->t = LTTV_STATE_USER_MODE;
3229 }
cab321cf 3230#endif //0
c4a72569 3231 /* Don't mess around with the stack, it will eventually become
3232 * ok after the end of state dump. */
80e0221b 3233 }
b3fd4c02 3234 }
3235
3236 return FALSE;
3237}
f4b88a7d 3238
58c88a41 3239gint lttv_state_hook_add_event_hooks(void *hook_data, void *call_data)
3240{
3241 LttvTracesetState *tss = (LttvTracesetState*)(call_data);
3242
3243 lttv_state_add_event_hooks(tss);
3244
3245 return 0;
3246}
dc877563 3247
308711e5 3248void lttv_state_add_event_hooks(LttvTracesetState *self)
dc877563 3249{
ba576a78 3250 LttvTraceset *traceset = self->parent.ts;
dc877563 3251
8979f265 3252 guint i, j, k, nb_trace, nb_tracefile;
dc877563 3253
ba576a78 3254 LttvTraceState *ts;
dc877563 3255
ba576a78 3256 LttvTracefileState *tfs;
dc877563 3257
dc877563 3258 GArray *hooks;
3259
0ceef9de 3260 LttvTraceHook *th;
eed2ef37 3261
dc877563 3262 LttvAttributeValue val;
3263
ba576a78 3264 nb_trace = lttv_traceset_number(traceset);
dc877563 3265 for(i = 0 ; i < nb_trace ; i++) {
ba576a78 3266 ts = (LttvTraceState *)self->parent.traces[i];
dc877563 3267
3268 /* Find the eventtype id for the following events and register the
3269 associated by id hooks. */
3270
c3b3b60b 3271 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 19);
6418800d 3272 //hooks = g_array_set_size(hooks, 19); // Max possible number of hooks.
3273 //hn = 0;
b445142a 3274
6418800d 3275 lttv_trace_find_hook(ts->parent.t,
60c5092c 3276 LTT_FACILITY_KERNEL_ARCH,
0ceef9de 3277 LTT_EVENT_SYSCALL_ENTRY,
6418800d 3278 FIELD_ARRAY(LTT_FIELD_SYSCALL_ID),
3279 syscall_entry, NULL, &hooks);
cbe7c836 3280
6418800d 3281 lttv_trace_find_hook(ts->parent.t,
60c5092c 3282 LTT_FACILITY_KERNEL_ARCH,
0ceef9de 3283 LTT_EVENT_SYSCALL_EXIT,
032ba5da 3284 NULL,
6418800d 3285 syscall_exit, NULL, &hooks);
cbe7c836 3286
6418800d 3287 lttv_trace_find_hook(ts->parent.t,
60c5092c 3288 LTT_FACILITY_KERNEL_ARCH,
0ceef9de 3289 LTT_EVENT_TRAP_ENTRY,
6418800d 3290 FIELD_ARRAY(LTT_FIELD_TRAP_ID),
3291 trap_entry, NULL, &hooks);
cbe7c836 3292
032ba5da 3293 lttv_trace_find_hook(ts->parent.t,
60c5092c 3294 LTT_FACILITY_KERNEL_ARCH,
0ceef9de 3295 LTT_EVENT_TRAP_EXIT,
032ba5da 3296 NULL,
3297 trap_exit, NULL, &hooks);
cbe7c836 3298
032ba5da 3299 lttv_trace_find_hook(ts->parent.t,
60c5092c 3300 LTT_FACILITY_KERNEL,
0ceef9de 3301 LTT_EVENT_IRQ_ENTRY,
032ba5da 3302 FIELD_ARRAY(LTT_FIELD_IRQ_ID),
3303 irq_entry, NULL, &hooks);
cbe7c836 3304
032ba5da 3305 lttv_trace_find_hook(ts->parent.t,
60c5092c 3306 LTT_FACILITY_KERNEL,
0ceef9de 3307 LTT_EVENT_IRQ_EXIT,
032ba5da 3308 NULL,
3309 irq_exit, NULL, &hooks);
cbe7c836 3310
032ba5da 3311 lttv_trace_find_hook(ts->parent.t,
60c5092c 3312 LTT_FACILITY_KERNEL,
0ceef9de 3313 LTT_EVENT_SOFT_IRQ_ENTRY,
032ba5da 3314 FIELD_ARRAY(LTT_FIELD_SOFT_IRQ_ID),
3315 soft_irq_entry, NULL, &hooks);
faf074a3 3316
032ba5da 3317 lttv_trace_find_hook(ts->parent.t,
60c5092c 3318 LTT_FACILITY_KERNEL,
0ceef9de 3319 LTT_EVENT_SOFT_IRQ_EXIT,
032ba5da 3320 NULL,
3321 soft_irq_exit, NULL, &hooks);
faf074a3 3322
032ba5da 3323 lttv_trace_find_hook(ts->parent.t,
60c5092c 3324 LTT_FACILITY_KERNEL,
0ceef9de 3325 LTT_EVENT_SCHED_SCHEDULE,
032ba5da 3326 FIELD_ARRAY(LTT_FIELD_PREV_PID, LTT_FIELD_NEXT_PID,
3327 LTT_FIELD_PREV_STATE),
3328 schedchange, NULL, &hooks);
cbe7c836 3329
032ba5da 3330 lttv_trace_find_hook(ts->parent.t,
60c5092c 3331 LTT_FACILITY_KERNEL,
0ceef9de 3332 LTT_EVENT_PROCESS_FORK,
032ba5da 3333 FIELD_ARRAY(LTT_FIELD_PARENT_PID, LTT_FIELD_CHILD_PID,
3334 LTT_FIELD_CHILD_TGID),
3335 process_fork, NULL, &hooks);
eed2ef37 3336
032ba5da 3337 lttv_trace_find_hook(ts->parent.t,
60c5092c 3338 LTT_FACILITY_KERNEL_ARCH,
0ceef9de 3339 LTT_EVENT_KTHREAD_CREATE,
370231d7 3340 FIELD_ARRAY(LTT_FIELD_PID),
032ba5da 3341 process_kernel_thread, NULL, &hooks);
7bfd7820 3342
032ba5da 3343 lttv_trace_find_hook(ts->parent.t,
60c5092c 3344 LTT_FACILITY_KERNEL,
0ceef9de 3345 LTT_EVENT_PROCESS_EXIT,
032ba5da 3346 FIELD_ARRAY(LTT_FIELD_PID),
3347 process_exit, NULL, &hooks);
eed2ef37 3348
032ba5da 3349 lttv_trace_find_hook(ts->parent.t,
60c5092c 3350 LTT_FACILITY_KERNEL,
0ceef9de 3351 LTT_EVENT_PROCESS_FREE,
032ba5da 3352 FIELD_ARRAY(LTT_FIELD_PID),
3353 process_free, NULL, &hooks);
2cdc690b 3354
032ba5da 3355 lttv_trace_find_hook(ts->parent.t,
43fb1d98 3356 LTT_FACILITY_FS,
0ceef9de 3357 LTT_EVENT_EXEC,
032ba5da 3358 FIELD_ARRAY(LTT_FIELD_FILENAME),
3359 process_exec, NULL, &hooks);
f4b88a7d 3360
032ba5da 3361 lttv_trace_find_hook(ts->parent.t,
60c5092c 3362 LTT_FACILITY_USER_GENERIC,
0ceef9de 3363 LTT_EVENT_THREAD_BRAND,
032ba5da 3364 FIELD_ARRAY(LTT_FIELD_NAME),
3365 thread_brand, NULL, &hooks);
7b5f6cf1 3366
b3fd4c02 3367 /* statedump-related hooks */
032ba5da 3368 lttv_trace_find_hook(ts->parent.t,
60c5092c 3369 LTT_FACILITY_LIST,
0ceef9de 3370 LTT_EVENT_PROCESS_STATE,
d3a66443 3371 FIELD_ARRAY(LTT_FIELD_PID, LTT_FIELD_PARENT_PID, LTT_FIELD_NAME,
3372 LTT_FIELD_TYPE, LTT_FIELD_MODE, LTT_FIELD_SUBMODE,
3373 LTT_FIELD_STATUS, LTT_FIELD_TGID),
032ba5da 3374 enum_process_state, NULL, &hooks);
f4b88a7d 3375
032ba5da 3376 lttv_trace_find_hook(ts->parent.t,
60c5092c 3377 LTT_FACILITY_LIST,
0ceef9de 3378 LTT_EVENT_STATEDUMP_END,
032ba5da 3379 NULL,
3380 statedump_end, NULL, &hooks);
c3b3b60b 3381
032ba5da 3382 lttv_trace_find_hook(ts->parent.t,
60c5092c 3383 LTT_FACILITY_LIST,
0ceef9de 3384 LTT_EVENT_LIST_INTERRUPT,
43fb1d98 3385 FIELD_ARRAY(LTT_FIELD_ACTION, LTT_FIELD_IRQ_ID),
032ba5da 3386 enum_interrupt, NULL, &hooks);
38b73700 3387
032ba5da 3388 lttv_trace_find_hook(ts->parent.t,
60c5092c 3389 LTT_FACILITY_BLOCK,
0ceef9de 3390 LTT_EVENT_REQUEST_ISSUE,
032ba5da 3391 FIELD_ARRAY(LTT_FIELD_MAJOR, LTT_FIELD_MINOR, LTT_FIELD_OPERATION),
3392 bdev_request_issue, NULL, &hooks);
27811799 3393
032ba5da 3394 lttv_trace_find_hook(ts->parent.t,
60c5092c 3395 LTT_FACILITY_BLOCK,
0ceef9de 3396 LTT_EVENT_REQUEST_COMPLETE,
032ba5da 3397 FIELD_ARRAY(LTT_FIELD_MAJOR, LTT_FIELD_MINOR, LTT_FIELD_OPERATION),
3398 bdev_request_complete, NULL, &hooks);
27811799 3399
032ba5da 3400 lttv_trace_find_hook(ts->parent.t,
60c5092c 3401 LTT_FACILITY_USER_GENERIC,
0ceef9de 3402 LTT_EVENT_FUNCTION_ENTRY,
032ba5da 3403 FIELD_ARRAY(LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE),
3404 function_entry, NULL, &hooks);
302efbad 3405
032ba5da 3406 lttv_trace_find_hook(ts->parent.t,
60c5092c 3407 LTT_FACILITY_USER_GENERIC,
0ceef9de 3408 LTT_EVENT_FUNCTION_EXIT,
032ba5da 3409 FIELD_ARRAY(LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE),
3410 function_exit, NULL, &hooks);
302efbad 3411
cf453ac7 3412 lttv_trace_find_hook(ts->parent.t,
3413 LTT_FACILITY_STATEDUMP,
3414 LTT_EVENT_SYS_CALL_TABLE,
3415 FIELD_ARRAY(LTT_FIELD_ID, LTT_FIELD_ADDRESS, LTT_FIELD_SYMBOL),
3416 dump_syscall, NULL, &hooks);
3417
dc6b2467 3418 lttv_trace_find_hook(ts->parent.t,
3419 LTT_FACILITY_STATEDUMP,
3420 LTT_EVENT_SOFTIRQ_VEC,
3421 FIELD_ARRAY(LTT_FIELD_ID, LTT_FIELD_ADDRESS, LTT_FIELD_SYMBOL),
3422 dump_softirq, NULL, &hooks);
3423
a5ba1787 3424 /* Add these hooks to each event_by_id hooks list */
dc877563 3425
eed2ef37 3426 nb_tracefile = ts->parent.tracefiles->len;
dbb7bb09 3427
dc877563 3428 for(j = 0 ; j < nb_tracefile ; j++) {
eed2ef37 3429 tfs =
9d239bd9 3430 LTTV_TRACEFILE_STATE(g_array_index(ts->parent.tracefiles,
3431 LttvTracefileContext*, j));
dc877563 3432
3433 for(k = 0 ; k < hooks->len ; k++) {
8979f265 3434 th = &g_array_index(hooks, LttvTraceHook, k);
eed2ef37 3435 lttv_hooks_add(
5fd4c7a2 3436 lttv_hooks_by_id_find(tfs->parent.event_by_id, th->id),
3437 th->h,
3438 th,
eed2ef37 3439 LTTV_PRIO_STATE);
ffd54a90 3440 }
dc877563 3441 }
f0b795e0 3442 lttv_attribute_find(ts->parent.a, LTTV_STATE_HOOKS, LTTV_POINTER, &val);
ba576a78 3443 *(val.v_pointer) = hooks;
dc877563 3444 }
3445}
3446
58c88a41 3447gint lttv_state_hook_remove_event_hooks(void *hook_data, void *call_data)
3448{
3449 LttvTracesetState *tss = (LttvTracesetState*)(call_data);
3450
3451 lttv_state_remove_event_hooks(tss);
3452
3453 return 0;
3454}
dc877563 3455
308711e5 3456void lttv_state_remove_event_hooks(LttvTracesetState *self)
dc877563 3457{
ba576a78 3458 LttvTraceset *traceset = self->parent.ts;
dc877563 3459
8979f265 3460 guint i, j, k, nb_trace, nb_tracefile;
dc877563 3461
ba576a78 3462 LttvTraceState *ts;
dc877563 3463
ba576a78 3464 LttvTracefileState *tfs;
dc877563 3465
dc877563 3466 GArray *hooks;
3467
5fd4c7a2 3468 LttvTraceHook *th;
dc877563 3469
3470 LttvAttributeValue val;
3471
ba576a78 3472 nb_trace = lttv_traceset_number(traceset);
dc877563 3473 for(i = 0 ; i < nb_trace ; i++) {
021eeb41 3474 ts = LTTV_TRACE_STATE(self->parent.traces[i]);
7df20ca4 3475
f0b795e0 3476 lttv_attribute_find(ts->parent.a, LTTV_STATE_HOOKS, LTTV_POINTER, &val);
ba576a78 3477 hooks = *(val.v_pointer);
dc877563 3478
a5ba1787 3479 /* Remove these hooks from each event_by_id hooks list */
dc877563 3480
eed2ef37 3481 nb_tracefile = ts->parent.tracefiles->len;
dbb7bb09 3482
dc877563 3483 for(j = 0 ; j < nb_tracefile ; j++) {
eed2ef37 3484 tfs =
cb03932a 3485 LTTV_TRACEFILE_STATE(g_array_index(ts->parent.tracefiles,
3486 LttvTracefileContext*, j));
dc877563 3487
3488 for(k = 0 ; k < hooks->len ; k++) {
8979f265 3489 th = &g_array_index(hooks, LttvTraceHook, k);
eed2ef37 3490 lttv_hooks_remove_data(
5fd4c7a2 3491 lttv_hooks_by_id_find(tfs->parent.event_by_id, th->id),
3492 th->h,
3493 th);
ffd54a90 3494 }
dc877563 3495 }
032ba5da 3496 lttv_trace_hook_remove_all(&hooks);
dc877563 3497 g_array_free(hooks, TRUE);
3498 }
3499}
3500
eed2ef37 3501static gboolean state_save_event_hook(void *hook_data, void *call_data)
3502{
3503 guint *event_count = (guint*)hook_data;
3504
3505 /* Only save at LTTV_STATE_SAVE_INTERVAL */
3506 if(likely((*event_count)++ < LTTV_STATE_SAVE_INTERVAL))
3507 return FALSE;
3508 else
18c87975 3509 *event_count = 0;
eed2ef37 3510
3511 LttvTracefileState *self = (LttvTracefileState *)call_data;
3512
eed2ef37 3513 LttvTraceState *tcs = (LttvTraceState *)(self->parent.t_context);
3514
eed2ef37 3515 LttvAttribute *saved_states_tree, *saved_state_tree;
3516
3517 LttvAttributeValue value;
3518
3519 saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a,
3520 LTTV_STATE_SAVED_STATES);
3521 saved_state_tree = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
3522 value = lttv_attribute_add(saved_states_tree,
3523 lttv_attribute_get_number(saved_states_tree), LTTV_GOBJECT);
3524 *(value.v_gobject) = (GObject *)saved_state_tree;
3525 value = lttv_attribute_add(saved_state_tree, LTTV_STATE_TIME, LTTV_TIME);
3526 *(value.v_time) = self->parent.timestamp;
3527 lttv_state_save(tcs, saved_state_tree);
3528 g_debug("Saving state at time %lu.%lu", self->parent.timestamp.tv_sec,
3529 self->parent.timestamp.tv_nsec);
3530
3531 *(tcs->max_time_state_recomputed_in_seek) = self->parent.timestamp;
3532
3533 return FALSE;
3534}
3535
14aecf75 3536static gboolean state_save_after_trace_hook(void *hook_data, void *call_data)
3537{
3538 LttvTraceState *tcs = (LttvTraceState *)(call_data);
3539
3540 *(tcs->max_time_state_recomputed_in_seek) = tcs->parent.time_span.end_time;
3541
3542 return FALSE;
3543}
3544
ae3d0f50 3545guint lttv_state_current_cpu(LttvTracefileState *tfs)
3546{
80e0221b 3547 return tfs->cpu;
ae3d0f50 3548}
3549
3550
3551
eed2ef37 3552#if 0
08b1c66e 3553static gboolean block_start(void *hook_data, void *call_data)
308711e5 3554{
dbb7bb09 3555 LttvTracefileState *self = (LttvTracefileState *)call_data;
308711e5 3556
dbb7bb09 3557 LttvTracefileState *tfcs;
308711e5 3558
dbb7bb09 3559 LttvTraceState *tcs = (LttvTraceState *)(self->parent.t_context);
3560
3561 LttEventPosition *ep;
308711e5 3562
dbb7bb09 3563 guint i, nb_block, nb_event, nb_tracefile;
308711e5 3564
3565 LttTracefile *tf;
3566
3567 LttvAttribute *saved_states_tree, *saved_state_tree;
3568
3569 LttvAttributeValue value;
3570
dbb7bb09 3571 ep = ltt_event_position_new();
eed2ef37 3572
3573 nb_tracefile = tcs->parent.tracefiles->len;
dbb7bb09 3574
3575 /* Count the number of events added since the last block end in any
3576 tracefile. */
3577
3578 for(i = 0 ; i < nb_tracefile ; i++) {
eed2ef37 3579 tfcs =
3580 LTTV_TRACEFILE_STATE(&g_array_index(tcs->parent.tracefiles,
3581 LttvTracefileContext, i));
dbb7bb09 3582 ltt_event_position(tfcs->parent.e, ep);
3583 ltt_event_position_get(ep, &nb_block, &nb_event, &tf);
3584 tcs->nb_event += nb_event - tfcs->saved_position;
3585 tfcs->saved_position = nb_event;
3586 }
3587 g_free(ep);
308711e5 3588
308711e5 3589 if(tcs->nb_event >= tcs->save_interval) {
3590 saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a,
3591 LTTV_STATE_SAVED_STATES);
3592 saved_state_tree = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
3593 value = lttv_attribute_add(saved_states_tree,
3594 lttv_attribute_get_number(saved_states_tree), LTTV_GOBJECT);
3595 *(value.v_gobject) = (GObject *)saved_state_tree;
3596 value = lttv_attribute_add(saved_state_tree, LTTV_STATE_TIME, LTTV_TIME);
dbb7bb09 3597 *(value.v_time) = self->parent.timestamp;
308711e5 3598 lttv_state_save(tcs, saved_state_tree);
3599 tcs->nb_event = 0;
08b1c66e 3600 g_debug("Saving state at time %lu.%lu", self->parent.timestamp.tv_sec,
80e0221b 3601 self->parent.timestamp.tv_nsec);
308711e5 3602 }
dbb7bb09 3603 *(tcs->max_time_state_recomputed_in_seek) = self->parent.timestamp;
308711e5 3604 return FALSE;
3605}
eed2ef37 3606#endif //0
308711e5 3607
eed2ef37 3608#if 0
08b1c66e 3609static gboolean block_end(void *hook_data, void *call_data)
3610{
3611 LttvTracefileState *self = (LttvTracefileState *)call_data;
3612
3613 LttvTraceState *tcs = (LttvTraceState *)(self->parent.t_context);
3614
3615 LttTracefile *tf;
3616
3617 LttEventPosition *ep;
3618
3619 guint nb_block, nb_event;
3620
3621 ep = ltt_event_position_new();
3622 ltt_event_position(self->parent.e, ep);
3623 ltt_event_position_get(ep, &nb_block, &nb_event, &tf);
3624 tcs->nb_event += nb_event - self->saved_position + 1;
3625 self->saved_position = 0;
3626 *(tcs->max_time_state_recomputed_in_seek) = self->parent.timestamp;
3627 g_free(ep);
00e74b69 3628
3629 return FALSE;
08b1c66e 3630}
eed2ef37 3631#endif //0
3632#if 0
308711e5 3633void lttv_state_save_add_event_hooks(LttvTracesetState *self)
3634{
3635 LttvTraceset *traceset = self->parent.ts;
3636
00e74b69 3637 guint i, j, nb_trace, nb_tracefile;
308711e5 3638
3639 LttvTraceState *ts;
3640
3641 LttvTracefileState *tfs;
3642
08b1c66e 3643 LttvTraceHook hook_start, hook_end;
308711e5 3644
3645 nb_trace = lttv_traceset_number(traceset);
3646 for(i = 0 ; i < nb_trace ; i++) {
3647 ts = (LttvTraceState *)self->parent.traces[i];
eed2ef37 3648
08b1c66e 3649 lttv_trace_find_hook(ts->parent.t, "core","block_start",NULL,
80e0221b 3650 NULL, NULL, block_start, &hook_start);
308711e5 3651 lttv_trace_find_hook(ts->parent.t, "core","block_end",NULL,
80e0221b 3652 NULL, NULL, block_end, &hook_end);
308711e5 3653
eed2ef37 3654 nb_tracefile = ts->parent.tracefiles->len;
308711e5 3655
dbb7bb09 3656 for(j = 0 ; j < nb_tracefile ; j++) {
eed2ef37 3657 tfs =
3658 LTTV_TRACEFILE_STATE(&g_array_index(ts->parent.tracefiles,
3659 LttvTracefileContext, j));
a5ba1787 3660 lttv_hooks_add(lttv_hooks_by_id_find(tfs->parent.event_by_id,
80e0221b 3661 hook_start.id), hook_start.h, NULL, LTTV_PRIO_STATE);
a5ba1787 3662 lttv_hooks_add(lttv_hooks_by_id_find(tfs->parent.event_by_id,
80e0221b 3663 hook_end.id), hook_end.h, NULL, LTTV_PRIO_STATE);
eed2ef37 3664 }
3665 }
3666}
3667#endif //0
3668
3669void lttv_state_save_add_event_hooks(LttvTracesetState *self)
3670{
3671 LttvTraceset *traceset = self->parent.ts;
3672
3673 guint i, j, nb_trace, nb_tracefile;
3674
3675 LttvTraceState *ts;
3676
3677 LttvTracefileState *tfs;
3678
3679
3680 nb_trace = lttv_traceset_number(traceset);
3681 for(i = 0 ; i < nb_trace ; i++) {
3682
3683 ts = (LttvTraceState *)self->parent.traces[i];
3684 nb_tracefile = ts->parent.tracefiles->len;
3685
ce05e187 3686 if(ts->has_precomputed_states) continue;
3687
3054461a 3688 guint *event_count = g_new(guint, 1);
3689 *event_count = 0;
3690
eed2ef37 3691 for(j = 0 ; j < nb_tracefile ; j++) {
3692 tfs =
cb03932a 3693 LTTV_TRACEFILE_STATE(g_array_index(ts->parent.tracefiles,
3694 LttvTracefileContext*, j));
eed2ef37 3695 lttv_hooks_add(tfs->parent.event,
3696 state_save_event_hook,
3697 event_count,
3698 LTTV_PRIO_STATE);
3699
308711e5 3700 }
3701 }
14aecf75 3702
3703 lttv_process_traceset_begin(&self->parent,
3704 NULL, NULL, NULL, NULL, NULL);
3705
308711e5 3706}
3707
b56b5fec 3708gint lttv_state_save_hook_add_event_hooks(void *hook_data, void *call_data)
3709{
3710 LttvTracesetState *tss = (LttvTracesetState*)(call_data);
3711
3712 lttv_state_save_add_event_hooks(tss);
3713
3714 return 0;
3715}
3716
308711e5 3717
eed2ef37 3718#if 0
308711e5 3719void lttv_state_save_remove_event_hooks(LttvTracesetState *self)
3720{
3721 LttvTraceset *traceset = self->parent.ts;
3722
00e74b69 3723 guint i, j, nb_trace, nb_tracefile;
308711e5 3724
3725 LttvTraceState *ts;
3726
3727 LttvTracefileState *tfs;
3728
08b1c66e 3729 LttvTraceHook hook_start, hook_end;
308711e5 3730
3731 nb_trace = lttv_traceset_number(traceset);
3732 for(i = 0 ; i < nb_trace ; i++) {
3733 ts = LTTV_TRACE_STATE(self->parent.traces[i]);
eed2ef37 3734
08b1c66e 3735 lttv_trace_find_hook(ts->parent.t, "core","block_start",NULL,
80e0221b 3736 NULL, NULL, block_start, &hook_start);
08b1c66e 3737
308711e5 3738 lttv_trace_find_hook(ts->parent.t, "core","block_end",NULL,
80e0221b 3739 NULL, NULL, block_end, &hook_end);
308711e5 3740
eed2ef37 3741 nb_tracefile = ts->parent.tracefiles->len;
308711e5 3742
dbb7bb09 3743 for(j = 0 ; j < nb_tracefile ; j++) {
eed2ef37 3744 tfs =
3745 LTTV_TRACEFILE_STATE(&g_array_index(ts->parent.tracefiles,
3746 LttvTracefileContext, j));
308711e5 3747 lttv_hooks_remove_data(lttv_hooks_by_id_find(
a5ba1787 3748 tfs->parent.event_by_id, hook_start.id), hook_start.h, NULL);
08b1c66e 3749 lttv_hooks_remove_data(lttv_hooks_by_id_find(
a5ba1787 3750 tfs->parent.event_by_id, hook_end.id), hook_end.h, NULL);
308711e5 3751 }
3752 }
3753}
eed2ef37 3754#endif //0
3755
3756void lttv_state_save_remove_event_hooks(LttvTracesetState *self)
3757{
3758 LttvTraceset *traceset = self->parent.ts;
3759
3760 guint i, j, nb_trace, nb_tracefile;
3761
3762 LttvTraceState *ts;
3763
3764 LttvTracefileState *tfs;
3765
14aecf75 3766 LttvHooks *after_trace = lttv_hooks_new();
3767
3768 lttv_hooks_add(after_trace,
3769 state_save_after_trace_hook,
3770 NULL,
3771 LTTV_PRIO_STATE);
3772
3773
3774 lttv_process_traceset_end(&self->parent,
3775 NULL, after_trace, NULL, NULL, NULL);
eed2ef37 3776
14aecf75 3777 lttv_hooks_destroy(after_trace);
3778
eed2ef37 3779 nb_trace = lttv_traceset_number(traceset);
3780 for(i = 0 ; i < nb_trace ; i++) {
3781
3782 ts = (LttvTraceState *)self->parent.traces[i];
3783 nb_tracefile = ts->parent.tracefiles->len;
3784
ce05e187 3785 if(ts->has_precomputed_states) continue;
3786
22b165e9 3787 guint *event_count = NULL;
eed2ef37 3788
3789 for(j = 0 ; j < nb_tracefile ; j++) {
3790 tfs =
cb03932a 3791 LTTV_TRACEFILE_STATE(g_array_index(ts->parent.tracefiles,
3792 LttvTracefileContext*, j));
eed2ef37 3793 event_count = lttv_hooks_remove(tfs->parent.event,
3794 state_save_event_hook);
eed2ef37 3795 }
22b165e9 3796 if(event_count) g_free(event_count);
eed2ef37 3797 }
3798}
308711e5 3799
b56b5fec 3800gint lttv_state_save_hook_remove_event_hooks(void *hook_data, void *call_data)
3801{
3802 LttvTracesetState *tss = (LttvTracesetState*)(call_data);
3803
3804 lttv_state_save_remove_event_hooks(tss);
3805
3806 return 0;
3807}
308711e5 3808
dd025f91 3809void lttv_state_traceset_seek_time_closest(LttvTracesetState *self, LttTime t)
308711e5 3810{
3811 LttvTraceset *traceset = self->parent.ts;
3812
00e74b69 3813 guint i, nb_trace;
308711e5 3814
3815 int min_pos, mid_pos, max_pos;
3816
728d0c3e 3817 guint call_rest = 0;
3818
308711e5 3819 LttvTraceState *tcs;
3820
3821 LttvAttributeValue value;
3822
3823 LttvAttributeType type;
3824
3825 LttvAttributeName name;
3826
80e0221b 3827 gboolean is_named;
c0cb4d12 3828
308711e5 3829 LttvAttribute *saved_states_tree, *saved_state_tree, *closest_tree;
3830
d448fce2 3831 //g_tree_destroy(self->parent.pqueue);
3832 //self->parent.pqueue = g_tree_new(compare_tracefile);
348c6ba8 3833
728d0c3e 3834 g_info("Entering seek_time_closest for time %lu.%lu", t.tv_sec, t.tv_nsec);
3835
308711e5 3836 nb_trace = lttv_traceset_number(traceset);
3837 for(i = 0 ; i < nb_trace ; i++) {
3838 tcs = (LttvTraceState *)self->parent.traces[i];
3839
2a2fa4f0 3840 if(ltt_time_compare(t, *(tcs->max_time_state_recomputed_in_seek)) < 0) {
3841 saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a,
3842 LTTV_STATE_SAVED_STATES);
3843 min_pos = -1;
3844
3845 if(saved_states_tree) {
dd025f91 3846 max_pos = lttv_attribute_get_number(saved_states_tree) - 1;
3847 mid_pos = max_pos / 2;
3848 while(min_pos < max_pos) {
c0cb4d12 3849 type = lttv_attribute_get(saved_states_tree, mid_pos, &name, &value,
80e0221b 3850 &is_named);
dd025f91 3851 g_assert(type == LTTV_GOBJECT);
3852 saved_state_tree = *((LttvAttribute **)(value.v_gobject));
3853 type = lttv_attribute_get_by_name(saved_state_tree, LTTV_STATE_TIME,
3854 &value);
3855 g_assert(type == LTTV_TIME);
3856 if(ltt_time_compare(*(value.v_time), t) < 0) {
3857 min_pos = mid_pos;
3858 closest_tree = saved_state_tree;
3859 }
3860 else max_pos = mid_pos - 1;
3861
3862 mid_pos = (min_pos + max_pos + 1) / 2;
3863 }
2a2fa4f0 3864 }
dd025f91 3865
2a2fa4f0 3866 /* restore the closest earlier saved state */
f95bc830 3867 if(min_pos != -1) {
3868 lttv_state_restore(tcs, closest_tree);
728d0c3e 3869 call_rest = 1;
f95bc830 3870 }
dd025f91 3871
2a2fa4f0 3872 /* There is no saved state, yet we want to have it. Restart at T0 */
dd025f91 3873 else {
3874 restore_init_state(tcs);
3875 lttv_process_trace_seek_time(&(tcs->parent), ltt_time_zero);
308711e5 3876 }
9444deae 3877 }
dd025f91 3878 /* We want to seek quickly without restoring/updating the state */
3879 else {
308711e5 3880 restore_init_state(tcs);
dd025f91 3881 lttv_process_trace_seek_time(&(tcs->parent), t);
308711e5 3882 }
308711e5 3883 }
728d0c3e 3884 if(!call_rest) g_info("NOT Calling restore");
308711e5 3885}
3886
3887
3888static void
3889traceset_state_instance_init (GTypeInstance *instance, gpointer g_class)
3890{
3891}
3892
3893
3894static void
3895traceset_state_finalize (LttvTracesetState *self)
3896{
3897 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))->
3898 finalize(G_OBJECT(self));
3899}
3900
3901
3902static void
3903traceset_state_class_init (LttvTracesetContextClass *klass)
3904{
3905 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
3906
3907 gobject_class->finalize = (void (*)(GObject *self)) traceset_state_finalize;
3908 klass->init = (void (*)(LttvTracesetContext *self, LttvTraceset *ts))init;
3909 klass->fini = (void (*)(LttvTracesetContext *self))fini;
3910 klass->new_traceset_context = new_traceset_context;
3911 klass->new_trace_context = new_trace_context;
3912 klass->new_tracefile_context = new_tracefile_context;
3913}
3914
3915
3916GType
3917lttv_traceset_state_get_type(void)
3918{
3919 static GType type = 0;
3920 if (type == 0) {
3921 static const GTypeInfo info = {
3922 sizeof (LttvTracesetStateClass),
3923 NULL, /* base_init */
3924 NULL, /* base_finalize */
3925 (GClassInitFunc) traceset_state_class_init, /* class_init */
3926 NULL, /* class_finalize */
3927 NULL, /* class_data */
dbb7bb09 3928 sizeof (LttvTracesetState),
308711e5 3929 0, /* n_preallocs */
00e74b69 3930 (GInstanceInitFunc) traceset_state_instance_init, /* instance_init */
3931 NULL /* value handling */
308711e5 3932 };
3933
3934 type = g_type_register_static (LTTV_TRACESET_CONTEXT_TYPE, "LttvTracesetStateType",
3935 &info, 0);
3936 }
3937 return type;
3938}
3939
3940
3941static void
3942trace_state_instance_init (GTypeInstance *instance, gpointer g_class)
3943{
3944}
3945
3946
3947static void
3948trace_state_finalize (LttvTraceState *self)
3949{
3950 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_CONTEXT_TYPE))->
3951 finalize(G_OBJECT(self));
3952}
3953
3954
3955static void
3956trace_state_class_init (LttvTraceStateClass *klass)
3957{
3958 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
3959
3960 gobject_class->finalize = (void (*)(GObject *self)) trace_state_finalize;
3961 klass->state_save = state_save;
3962 klass->state_restore = state_restore;
3963 klass->state_saved_free = state_saved_free;
3964}
3965
3966
3967GType
3968lttv_trace_state_get_type(void)
3969{
3970 static GType type = 0;
3971 if (type == 0) {
3972 static const GTypeInfo info = {
3973 sizeof (LttvTraceStateClass),
3974 NULL, /* base_init */
3975 NULL, /* base_finalize */
3976 (GClassInitFunc) trace_state_class_init, /* class_init */
3977 NULL, /* class_finalize */
3978 NULL, /* class_data */
3979 sizeof (LttvTraceState),
3980 0, /* n_preallocs */
00e74b69 3981 (GInstanceInitFunc) trace_state_instance_init, /* instance_init */
3982 NULL /* value handling */
308711e5 3983 };
3984
3985 type = g_type_register_static (LTTV_TRACE_CONTEXT_TYPE,
3986 "LttvTraceStateType", &info, 0);
3987 }
3988 return type;
3989}
3990
3991
3992static void
3993tracefile_state_instance_init (GTypeInstance *instance, gpointer g_class)
3994{
3995}
3996
3997
3998static void
3999tracefile_state_finalize (LttvTracefileState *self)
4000{
4001 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_CONTEXT_TYPE))->
4002 finalize(G_OBJECT(self));
4003}
4004
4005
4006static void
4007tracefile_state_class_init (LttvTracefileStateClass *klass)
4008{
4009 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
4010
4011 gobject_class->finalize = (void (*)(GObject *self)) tracefile_state_finalize;
4012}
4013
4014
4015GType
4016lttv_tracefile_state_get_type(void)
4017{
4018 static GType type = 0;
4019 if (type == 0) {
4020 static const GTypeInfo info = {
4021 sizeof (LttvTracefileStateClass),
4022 NULL, /* base_init */
4023 NULL, /* base_finalize */
4024 (GClassInitFunc) tracefile_state_class_init, /* class_init */
4025 NULL, /* class_finalize */
4026 NULL, /* class_data */
4027 sizeof (LttvTracefileState),
4028 0, /* n_preallocs */
00e74b69 4029 (GInstanceInitFunc) tracefile_state_instance_init, /* instance_init */
4030 NULL /* value handling */
308711e5 4031 };
4032
4033 type = g_type_register_static (LTTV_TRACEFILE_CONTEXT_TYPE,
4034 "LttvTracefileStateType", &info, 0);
4035 }
4036 return type;
4037}
4038
4039
08b1c66e 4040static void module_init()
ffd54a90 4041{
b4fa748c 4042 LTTV_STATE_UNNAMED = g_quark_from_string("");
235c78f0 4043 LTTV_STATE_UNBRANDED = g_quark_from_string("");
b3fd4c02 4044 LTTV_STATE_MODE_UNKNOWN = g_quark_from_string("MODE_UNKNOWN");
4045 LTTV_STATE_USER_MODE = g_quark_from_string("USER_MODE");
4046 LTTV_STATE_SYSCALL = g_quark_from_string("SYSCALL");
4047 LTTV_STATE_TRAP = g_quark_from_string("TRAP");
4048 LTTV_STATE_IRQ = g_quark_from_string("IRQ");
4049 LTTV_STATE_SOFT_IRQ = g_quark_from_string("SOFTIRQ");
4050 LTTV_STATE_SUBMODE_UNKNOWN = g_quark_from_string("UNKNOWN");
4051 LTTV_STATE_SUBMODE_NONE = g_quark_from_string("NONE");
4052 LTTV_STATE_WAIT_FORK = g_quark_from_string("WAIT_FORK");
4053 LTTV_STATE_WAIT_CPU = g_quark_from_string("WAIT_CPU");
4054 LTTV_STATE_EXIT = g_quark_from_string("EXIT");
4055 LTTV_STATE_ZOMBIE = g_quark_from_string("ZOMBIE");
4056 LTTV_STATE_WAIT = g_quark_from_string("WAIT");
4057 LTTV_STATE_RUN = g_quark_from_string("RUN");
4058 LTTV_STATE_DEAD = g_quark_from_string("DEAD");
80e0221b 4059 LTTV_STATE_USER_THREAD = g_quark_from_string("USER_THREAD");
4060 LTTV_STATE_KERNEL_THREAD = g_quark_from_string("KERNEL_THREAD");
308711e5 4061 LTTV_STATE_TRACEFILES = g_quark_from_string("tracefiles");
4062 LTTV_STATE_PROCESSES = g_quark_from_string("processes");
4063 LTTV_STATE_PROCESS = g_quark_from_string("process");
348c6ba8 4064 LTTV_STATE_RUNNING_PROCESS = g_quark_from_string("running_process");
308711e5 4065 LTTV_STATE_EVENT = g_quark_from_string("event");
4066 LTTV_STATE_SAVED_STATES = g_quark_from_string("saved states");
dbb7bb09 4067 LTTV_STATE_SAVED_STATES_TIME = g_quark_from_string("saved states time");
308711e5 4068 LTTV_STATE_TIME = g_quark_from_string("time");
ffd54a90 4069 LTTV_STATE_HOOKS = g_quark_from_string("saved state hooks");
f95bc830 4070 LTTV_STATE_NAME_TABLES = g_quark_from_string("name tables");
4071 LTTV_STATE_TRACE_STATE_USE_COUNT =
4072 g_quark_from_string("trace_state_use_count");
fbfbd4db 4073 LTTV_STATE_RESOURCE_CPUS = g_quark_from_string("cpu resource states");
f61bce48 4074 LTTV_STATE_RESOURCE_CPUS = g_quark_from_string("cpu count");
98d7814f 4075 LTTV_STATE_RESOURCE_IRQS = g_quark_from_string("irq resource states");
0305fe77 4076 LTTV_STATE_RESOURCE_SOFT_IRQS = g_quark_from_string("soft irq resource states");
38726a78 4077 LTTV_STATE_RESOURCE_TRAPS = g_quark_from_string("trap resource states");
98d7814f 4078 LTTV_STATE_RESOURCE_BLKDEVS = g_quark_from_string("blkdevs resource states");
eed2ef37 4079
4080
4081 LTT_FACILITY_KERNEL = g_quark_from_string("kernel");
f5d7967f 4082 LTT_FACILITY_KERNEL_ARCH = g_quark_from_string("kernel_arch");
f4b88a7d 4083 LTT_FACILITY_FS = g_quark_from_string("fs");
86c32a8f 4084 LTT_FACILITY_LIST = g_quark_from_string("list");
302efbad 4085 LTT_FACILITY_USER_GENERIC = g_quark_from_string("user_generic");
27811799 4086 LTT_FACILITY_BLOCK = g_quark_from_string("block");
cf453ac7 4087 LTT_FACILITY_STATEDUMP = g_quark_from_string("statedump");
4088
eed2ef37 4089 LTT_EVENT_SYSCALL_ENTRY = g_quark_from_string("syscall_entry");
4090 LTT_EVENT_SYSCALL_EXIT = g_quark_from_string("syscall_exit");
4091 LTT_EVENT_TRAP_ENTRY = g_quark_from_string("trap_entry");
4092 LTT_EVENT_TRAP_EXIT = g_quark_from_string("trap_exit");
4093 LTT_EVENT_IRQ_ENTRY = g_quark_from_string("irq_entry");
4094 LTT_EVENT_IRQ_EXIT = g_quark_from_string("irq_exit");
43fb1d98 4095 LTT_EVENT_SOFT_IRQ_ENTRY = g_quark_from_string("softirq_entry");
4096 LTT_EVENT_SOFT_IRQ_EXIT = g_quark_from_string("softirq_exit");
86c32a8f 4097 LTT_EVENT_SCHED_SCHEDULE = g_quark_from_string("sched_schedule");
4098 LTT_EVENT_PROCESS_FORK = g_quark_from_string("process_fork");
4099 LTT_EVENT_KTHREAD_CREATE = g_quark_from_string("kthread_create");
4100 LTT_EVENT_PROCESS_EXIT = g_quark_from_string("process_exit");
f63ebe51 4101 LTT_EVENT_PROCESS_FREE = g_quark_from_string("process_free");
f4b88a7d 4102 LTT_EVENT_EXEC = g_quark_from_string("exec");
86c32a8f 4103 LTT_EVENT_PROCESS_STATE = g_quark_from_string("process_state");
c3b3b60b 4104 LTT_EVENT_STATEDUMP_END = g_quark_from_string("statedump_end");
302efbad 4105 LTT_EVENT_FUNCTION_ENTRY = g_quark_from_string("function_entry");
4106 LTT_EVENT_FUNCTION_EXIT = g_quark_from_string("function_exit");
7b5f6cf1 4107 LTT_EVENT_THREAD_BRAND = g_quark_from_string("thread_brand");
27811799 4108 LTT_EVENT_REQUEST_ISSUE = g_quark_from_string("_blk_request_issue");
4109 LTT_EVENT_REQUEST_COMPLETE = g_quark_from_string("_blk_request_complete");
cf453ac7 4110 LTT_EVENT_LIST_INTERRUPT = g_quark_from_string("interrupt");
4111 LTT_EVENT_SYS_CALL_TABLE = g_quark_from_string("sys_call_table");
dc6b2467 4112 LTT_EVENT_SOFTIRQ_VEC = g_quark_from_string("softirq_vec");
eed2ef37 4113
4114 LTT_FIELD_SYSCALL_ID = g_quark_from_string("syscall_id");
4115 LTT_FIELD_TRAP_ID = g_quark_from_string("trap_id");
4116 LTT_FIELD_IRQ_ID = g_quark_from_string("irq_id");
faf074a3 4117 LTT_FIELD_SOFT_IRQ_ID = g_quark_from_string("softirq_id");
f63ebe51 4118 LTT_FIELD_PREV_PID = g_quark_from_string("prev_pid");
4119 LTT_FIELD_NEXT_PID = g_quark_from_string("next_pid");
4120 LTT_FIELD_PREV_STATE = g_quark_from_string("prev_state");
eed2ef37 4121 LTT_FIELD_PARENT_PID = g_quark_from_string("parent_pid");
4122 LTT_FIELD_CHILD_PID = g_quark_from_string("child_pid");
4123 LTT_FIELD_PID = g_quark_from_string("pid");
fcc08e1e 4124 LTT_FIELD_TGID = g_quark_from_string("tgid");
f63ebe51 4125 LTT_FIELD_CHILD_TGID = g_quark_from_string("child_tgid");
f4b88a7d 4126 LTT_FIELD_FILENAME = g_quark_from_string("filename");
b3fd4c02 4127 LTT_FIELD_NAME = g_quark_from_string("name");
e62e7f3a 4128 LTT_FIELD_TYPE = g_quark_from_string("type");
b3fd4c02 4129 LTT_FIELD_MODE = g_quark_from_string("mode");
4130 LTT_FIELD_SUBMODE = g_quark_from_string("submode");
4131 LTT_FIELD_STATUS = g_quark_from_string("status");
302efbad 4132 LTT_FIELD_THIS_FN = g_quark_from_string("this_fn");
4133 LTT_FIELD_CALL_SITE = g_quark_from_string("call_site");
27811799 4134 LTT_FIELD_MAJOR = g_quark_from_string("major");
4135 LTT_FIELD_MINOR = g_quark_from_string("minor");
4136 LTT_FIELD_OPERATION = g_quark_from_string("direction");
38b73700 4137 LTT_FIELD_ACTION = g_quark_from_string("action");
cf453ac7 4138 LTT_FIELD_ID = g_quark_from_string("id");
4139 LTT_FIELD_ADDRESS = g_quark_from_string("address");
4140 LTT_FIELD_SYMBOL = g_quark_from_string("symbol");
eed2ef37 4141
44ffb95f 4142 LTTV_CPU_UNKNOWN = g_quark_from_string("unknown");
4143 LTTV_CPU_IDLE = g_quark_from_string("idle");
4144 LTTV_CPU_BUSY = g_quark_from_string("busy");
598026ba 4145 LTTV_CPU_IRQ = g_quark_from_string("irq");
d34141ca 4146 LTTV_CPU_SOFT_IRQ = g_quark_from_string("softirq");
d3d99fde 4147 LTTV_CPU_TRAP = g_quark_from_string("trap");
5e563da0 4148
4149 LTTV_IRQ_UNKNOWN = g_quark_from_string("unknown");
4150 LTTV_IRQ_IDLE = g_quark_from_string("idle");
4151 LTTV_IRQ_BUSY = g_quark_from_string("busy");
27811799 4152
4153 LTTV_BDEV_UNKNOWN = g_quark_from_string("unknown");
4154 LTTV_BDEV_IDLE = g_quark_from_string("idle");
4155 LTTV_BDEV_BUSY_READING = g_quark_from_string("busy_reading");
4156 LTTV_BDEV_BUSY_WRITING = g_quark_from_string("busy_writing");
ffd54a90 4157}
dc877563 4158
08b1c66e 4159static void module_destroy()
ffd54a90 4160{
4161}
dc877563 4162
4163
08b1c66e 4164LTTV_MODULE("state", "State computation", \
4165 "Update the system state, possibly saving it at intervals", \
4166 module_init, module_destroy)
4167
dc877563 4168
4169
This page took 0.31095 seconds and 4 git commands to generate.