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