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