X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=ltt%2Fbranches%2Fpoly%2Flttv%2Flttv%2Fstate.c;h=bcdf3ef8a3dbc7aa573c04fe528c571aa53fabc7;hb=61ab5e97ee7296773f7e0b8630752471c3d84e3d;hp=92c2aec5006797a6c2713515560fc62a887496c3;hpb=7ad3837aacd155c87986363f434f6a2fe5ce6546;p=lttv.git diff --git a/ltt/branches/poly/lttv/lttv/state.c b/ltt/branches/poly/lttv/lttv/state.c index 92c2aec5..bcdf3ef8 100644 --- a/ltt/branches/poly/lttv/lttv/state.c +++ b/ltt/branches/poly/lttv/lttv/state.c @@ -21,6 +21,7 @@ #include #endif +#include #include #include #include @@ -105,8 +106,7 @@ GQuark LTT_FIELD_MINOR, LTT_FIELD_MAJOR, LTT_FIELD_OPERATION, - LTT_FIELD_ACTION, - LTT_FIELD_NUM; + LTT_FIELD_ACTION; LttvExecutionMode LTTV_STATE_MODE_UNKNOWN, @@ -142,6 +142,7 @@ LttvCPUMode LTTV_CPU_IDLE, LTTV_CPU_BUSY, LTTV_CPU_IRQ, + LTTV_CPU_SOFT_IRQ, LTTV_CPU_TRAP; LttvIRQMode @@ -168,7 +169,9 @@ static GQuark LTTV_STATE_NAME_TABLES, LTTV_STATE_TRACE_STATE_USE_COUNT, LTTV_STATE_RESOURCE_CPUS, + LTTV_STATE_RESOURCE_CPUS_COUNT, LTTV_STATE_RESOURCE_IRQS, + LTTV_STATE_RESOURCE_SOFT_IRQS, LTTV_STATE_RESOURCE_BLKDEVS; static void create_max_time(LttvTraceState *tcs); @@ -252,12 +255,15 @@ static void lttv_state_free_usertraces(GHashTable *usertraces) g_hash_table_destroy(usertraces); } - +gboolean rettrue(gpointer key, gpointer value, gpointer user_data) +{ + return TRUE; +} static void restore_init_state(LttvTraceState *self) { - guint i, nb_cpus, nb_irqs; + guint i, nb_cpus, nb_irqs, nb_soft_irqs; //LttvTracefileState *tfcs; @@ -283,6 +289,7 @@ restore_init_state(LttvTraceState *self) nb_cpus = ltt_trace_get_num_cpu(self->parent.t); nb_irqs = self->nb_irqs; + nb_soft_irqs = self->nb_soft_irqs; /* Put the per cpu running_process to beginning state : process 0. */ for(i=0; i< nb_cpus; i++) { @@ -313,9 +320,15 @@ restore_init_state(LttvTraceState *self) g_array_remove_range(self->irq_states[i].mode_stack, 0, self->irq_states[i].mode_stack->len); } + /* reset softirq states */ + for(i=0; isoft_irq_states[i].running = 0; + } + /* reset bdev states */ g_hash_table_foreach(self->bdev_states, bdevstate_free_cb, NULL); - g_hash_table_steal_all(self->bdev_states); + //g_hash_table_steal_all(self->bdev_states); + g_hash_table_foreach_steal(self->bdev_states, rettrue, NULL); #if 0 nb_tracefile = self->parent.tracefiles->len; @@ -481,6 +494,10 @@ init(LttvTracesetState *self, LttvTraceset *ts) g_assert(tcs->irq_states[j].mode_stack != NULL); } + /* init soft irq stuff */ + /* the kernel has a statically fixed max of 32 softirqs */ + tcs->soft_irq_states = g_new(LttvSoftIRQState, tcs->nb_soft_irqs); + /* init bdev resource stuff */ tcs->bdev_states = g_hash_table_new(g_int_hash, g_int_equal); @@ -1154,7 +1171,7 @@ static void lttv_state_free_cpu_states(LttvCPUState *states, guint n) guint i; for(i=0; imode_stack, FALSE); + g_array_free(bds->mode_stack, TRUE); g_free(bds); } @@ -1351,6 +1387,10 @@ static void state_save(LttvTraceState *self, LttvAttribute *container) /* save the cpu state */ { + value = lttv_attribute_add(container, LTTV_STATE_RESOURCE_CPUS_COUNT, + LTTV_UINT); + *(value.v_uint) = nb_cpus; + value = lttv_attribute_add(container, LTTV_STATE_RESOURCE_CPUS, LTTV_POINTER); *(value.v_pointer) = lttv_state_copy_cpu_states(self->cpu_states, nb_cpus); @@ -1364,6 +1404,14 @@ static void state_save(LttvTraceState *self, LttvAttribute *container) *(value.v_pointer) = lttv_state_copy_irq_states(self->irq_states, nb_irqs); } + /* save the soft irq state */ + nb_irqs = self->nb_irqs; + { + value = lttv_attribute_add(container, LTTV_STATE_RESOURCE_SOFT_IRQS, + LTTV_POINTER); + *(value.v_pointer) = lttv_state_copy_soft_irq_states(self->soft_irq_states, nb_irqs); + } + /* save the blkdev states */ value = lttv_attribute_add(container, LTTV_STATE_RESOURCE_BLKDEVS, LTTV_POINTER); @@ -1373,7 +1421,7 @@ static void state_save(LttvTraceState *self, LttvAttribute *container) static void state_restore(LttvTraceState *self, LttvAttribute *container) { - guint i, nb_tracefile, pid, nb_cpus, nb_irqs; + guint i, nb_tracefile, pid, nb_cpus, nb_irqs, nb_soft_irqs; LttvTracefileState *tfcs; @@ -1432,6 +1480,13 @@ static void state_restore(LttvTraceState *self, LttvAttribute *container) lttv_state_free_irq_states(self->irq_states, nb_irqs); self->irq_states = lttv_state_copy_irq_states(*(value.v_pointer), nb_irqs); + /* restore soft irq resource states */ + nb_soft_irqs = self->nb_soft_irqs; + type = lttv_attribute_get_by_name(container, LTTV_STATE_RESOURCE_SOFT_IRQS, &value); + g_assert(type == LTTV_POINTER); + lttv_state_free_soft_irq_states(self->soft_irq_states, nb_soft_irqs); + self->soft_irq_states = lttv_state_copy_soft_irq_states(*(value.v_pointer), nb_soft_irqs); + /* restore the blkdev states */ type = lttv_attribute_get_by_name(container, LTTV_STATE_RESOURCE_BLKDEVS, &value); g_assert(type == LTTV_POINTER); @@ -1479,7 +1534,7 @@ static void state_restore(LttvTraceState *self, LttvAttribute *container) static void state_saved_free(LttvTraceState *self, LttvAttribute *container) { - guint i, nb_tracefile, nb_cpus; + guint i, nb_tracefile, nb_cpus, nb_irqs; LttvTracefileState *tfcs; @@ -1508,13 +1563,31 @@ static void state_saved_free(LttvTraceState *self, LttvAttribute *container) lttv_attribute_remove_by_name(container, LTTV_STATE_PROCESSES); /* Free running processes array */ - nb_cpus = ltt_trace_get_num_cpu(self->parent.t); type = lttv_attribute_get_by_name(container, LTTV_STATE_RUNNING_PROCESS, &value); g_assert(type == LTTV_POINTER); running_process = *(value.v_pointer); g_free(running_process); + /* free cpu resource states */ + type = lttv_attribute_get_by_name(container, LTTV_STATE_RESOURCE_CPUS_COUNT, &value); + g_assert(type == LTTV_UINT); + nb_cpus = *value.v_uint; + type = lttv_attribute_get_by_name(container, LTTV_STATE_RESOURCE_CPUS, &value); + g_assert(type == LTTV_POINTER); + lttv_state_free_cpu_states(*(value.v_pointer), nb_cpus); + + /* free irq resource states */ + nb_irqs = self->nb_irqs; + type = lttv_attribute_get_by_name(container, LTTV_STATE_RESOURCE_IRQS, &value); + g_assert(type == LTTV_POINTER); + lttv_state_free_irq_states(*(value.v_pointer), nb_irqs); + + /* free the blkdev states */ + type = lttv_attribute_get_by_name(container, LTTV_STATE_RESOURCE_BLKDEVS, &value); + g_assert(type == LTTV_POINTER); + lttv_state_free_blkdev_hashtable(*(value.v_pointer)); + nb_tracefile = self->parent.tracefiles->len; for(i = 0 ; i < nb_tracefile ; i++) { @@ -1633,6 +1706,7 @@ create_name_tables(LttvTraceState *tcs) hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 1); if(!lttv_trace_find_hook(tcs->parent.t, + LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_ENTRY, FIELD_ARRAY(LTT_FIELD_SYSCALL_ID), NULL, NULL, &hooks)) { @@ -1655,6 +1729,7 @@ create_name_tables(LttvTraceState *tcs) // } // } + name_tables->nb_syscalls = 256; name_tables->syscall_names = g_new(GQuark, 256); for(i = 0 ; i < 256 ; i++) { g_string_printf(fe_name, "syscall %d", i); @@ -1667,6 +1742,7 @@ create_name_tables(LttvTraceState *tcs) lttv_trace_hook_remove_all(&hooks); if(!lttv_trace_find_hook(tcs->parent.t, + LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_TRAP_ENTRY, FIELD_ARRAY(LTT_FIELD_TRAP_ID), NULL, NULL, &hooks)) { @@ -1695,6 +1771,7 @@ create_name_tables(LttvTraceState *tcs) lttv_trace_hook_remove_all(&hooks); if(!lttv_trace_find_hook(tcs->parent.t, + LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY, FIELD_ARRAY(LTT_FIELD_IRQ_ID), NULL, NULL, &hooks)) { @@ -1724,9 +1801,10 @@ create_name_tables(LttvTraceState *tcs) } */ - name_tables->nb_softirqs = 256; - name_tables->soft_irq_names = g_new(GQuark, 256); - for(i = 0 ; i < 256 ; i++) { + /* the kernel is limited to 32 statically defined softirqs */ + name_tables->nb_softirqs = 32; + name_tables->soft_irq_names = g_new(GQuark, name_tables->nb_softirqs); + for(i = 0 ; i < name_tables->nb_softirqs ; i++) { g_string_printf(fe_name, "softirq %d", i); name_tables->soft_irq_names[i] = g_quark_from_string(fe_name->str); } @@ -1755,7 +1833,7 @@ get_name_tables(LttvTraceState *tcs) tcs->irq_names = name_tables->irq_names; tcs->soft_irq_names = name_tables->soft_irq_names; tcs->nb_irqs = name_tables->nb_irqs; - tcs->nb_softirqs = name_tables->nb_softirqs; + tcs->nb_soft_irqs = name_tables->nb_softirqs; } @@ -2112,7 +2190,7 @@ lttv_state_find_process_or_create(LttvTraceState *ts, guint cpu, guint pid, * the parent waits for its child terminaison, but may also happen in special * cases in the child's exit : when the parent ignores its children SIGCCHLD or * has the flag SA_NOCLDWAIT. It can also happen when the child is part - * of a killed thread ground, but isn't the leader. + * of a killed thread group, but isn't the leader. */ static void exit_process(LttvTracefileState *tfs, LttvProcessState *process) { @@ -2270,12 +2348,20 @@ static gboolean irq_entry(void *hook_data, void *call_data) static gboolean soft_irq_exit(void *hook_data, void *call_data) { LttvTracefileState *s = (LttvTracefileState *)call_data; + LttvTraceState *ts = (LttvTraceState *)s->parent.t_context; + guint softirq = s->cpu_state->last_soft_irq; pop_state(s, LTTV_STATE_SOFT_IRQ); - return FALSE; -} + /* update softirq status */ + if(ts->soft_irq_states[softirq].running) + ts->soft_irq_states[softirq].running--; + /* update cpu status */ + cpu_pop_mode(s->cpu_state); + + return FALSE; +} static gboolean irq_exit(void *hook_data, void *call_data) { @@ -2296,6 +2382,7 @@ static gboolean irq_exit(void *hook_data, void *call_data) static gboolean soft_irq_entry(void *hook_data, void *call_data) { LttvTracefileState *s = (LttvTracefileState *)call_data; + LttvTraceState *ts = (LttvTraceState *)s->parent.t_context; LttEvent *e = ltt_tracefile_get_event(s->parent.tf); //guint8 ev_id = ltt_event_eventtype_id(e); LttvTraceHook *th = (LttvTraceHook *)hook_data; @@ -2303,7 +2390,7 @@ static gboolean soft_irq_entry(void *hook_data, void *call_data) LttvExecutionSubmode submode; guint64 softirq = ltt_event_get_long_unsigned(e, f); - guint64 nb_softirqs = ((LttvTraceState *)(s->parent.t_context))->nb_softirqs; + guint64 nb_softirqs = ((LttvTraceState *)(s->parent.t_context))->nb_soft_irqs; if(softirq < nb_softirqs) { submode = ((LttvTraceState *)(s->parent.t_context))->soft_irq_names[softirq]; @@ -2317,6 +2404,14 @@ static gboolean soft_irq_entry(void *hook_data, void *call_data) /* Do something with the info about being in user or system mode when int? */ push_state(s, LTTV_STATE_SOFT_IRQ, submode); + + /* update cpu status */ + cpu_push_mode(s->cpu_state, LTTV_CPU_SOFT_IRQ); + + /* update softirq status */ + s->cpu_state->last_soft_irq = softirq; + ts->soft_irq_states[softirq].running++; + return FALSE; } @@ -2519,7 +2614,7 @@ static gboolean schedchange(void *hook_data, void *call_data) process->state->change = s->parent.timestamp; } - if(state_out == 32 || state_out == 128) + if(state_out == 32 || state_out == 64) exit_process(s, process); /* EXIT_DEAD || TASK_DEAD */ /* see sched.h for states */ } @@ -2538,9 +2633,18 @@ static gboolean schedchange(void *hook_data, void *call_data) /* update cpu status */ if(pid_in == 0) + /* going to idle task */ cpu_set_base_mode(s->cpu_state, LTTV_CPU_IDLE); - else + else { + /* scheduling a real task. + * we must be careful here: + * if we just schedule()'ed to a process that is + * in a trap, we must put the cpu in trap mode + */ cpu_set_base_mode(s->cpu_state, LTTV_CPU_BUSY); + if(process->state->t == LTTV_STATE_TRAP) + cpu_push_mode(s->cpu_state, LTTV_CPU_TRAP); + } return FALSE; } @@ -2869,6 +2973,8 @@ static gboolean enum_process_state(void *hook_data, void *call_data) f = lttv_trace_get_hook_field(th, 3); type = ltt_enum_string_get(f, ltt_event_get_unsigned(e, f)); + //FIXME: type is rarely used, enum must match possible types. + /* mode */ f = lttv_trace_get_hook_field(th, 4); mode = ltt_enum_string_get(f,ltt_event_get_unsigned(e, f)); @@ -3034,84 +3140,100 @@ void lttv_state_add_event_hooks(LttvTracesetState *self) //hn = 0; lttv_trace_find_hook(ts->parent.t, + LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_ENTRY, FIELD_ARRAY(LTT_FIELD_SYSCALL_ID), syscall_entry, NULL, &hooks); lttv_trace_find_hook(ts->parent.t, + LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_EXIT, NULL, syscall_exit, NULL, &hooks); lttv_trace_find_hook(ts->parent.t, + LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_TRAP_ENTRY, FIELD_ARRAY(LTT_FIELD_TRAP_ID), trap_entry, NULL, &hooks); lttv_trace_find_hook(ts->parent.t, + LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_TRAP_EXIT, NULL, trap_exit, NULL, &hooks); lttv_trace_find_hook(ts->parent.t, + LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY, FIELD_ARRAY(LTT_FIELD_IRQ_ID), irq_entry, NULL, &hooks); lttv_trace_find_hook(ts->parent.t, + LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT, NULL, irq_exit, NULL, &hooks); lttv_trace_find_hook(ts->parent.t, + LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_ENTRY, FIELD_ARRAY(LTT_FIELD_SOFT_IRQ_ID), soft_irq_entry, NULL, &hooks); lttv_trace_find_hook(ts->parent.t, + LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_EXIT, NULL, soft_irq_exit, NULL, &hooks); lttv_trace_find_hook(ts->parent.t, + LTT_FACILITY_KERNEL, LTT_EVENT_SCHED_SCHEDULE, FIELD_ARRAY(LTT_FIELD_PREV_PID, LTT_FIELD_NEXT_PID, LTT_FIELD_PREV_STATE), schedchange, NULL, &hooks); lttv_trace_find_hook(ts->parent.t, + LTT_FACILITY_KERNEL, LTT_EVENT_PROCESS_FORK, FIELD_ARRAY(LTT_FIELD_PARENT_PID, LTT_FIELD_CHILD_PID, LTT_FIELD_CHILD_TGID), process_fork, NULL, &hooks); lttv_trace_find_hook(ts->parent.t, + LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_KTHREAD_CREATE, FIELD_ARRAY(LTT_FIELD_PID), process_kernel_thread, NULL, &hooks); lttv_trace_find_hook(ts->parent.t, + LTT_FACILITY_KERNEL, LTT_EVENT_PROCESS_EXIT, FIELD_ARRAY(LTT_FIELD_PID), process_exit, NULL, &hooks); lttv_trace_find_hook(ts->parent.t, + LTT_FACILITY_KERNEL, LTT_EVENT_PROCESS_FREE, FIELD_ARRAY(LTT_FIELD_PID), process_free, NULL, &hooks); lttv_trace_find_hook(ts->parent.t, + LTT_FACILITY_FS, LTT_EVENT_EXEC, FIELD_ARRAY(LTT_FIELD_FILENAME), process_exec, NULL, &hooks); lttv_trace_find_hook(ts->parent.t, + LTT_FACILITY_USER_GENERIC, LTT_EVENT_THREAD_BRAND, FIELD_ARRAY(LTT_FIELD_NAME), thread_brand, NULL, &hooks); /* statedump-related hooks */ lttv_trace_find_hook(ts->parent.t, + LTT_FACILITY_LIST, LTT_EVENT_PROCESS_STATE, FIELD_ARRAY(LTT_FIELD_PID, LTT_FIELD_PARENT_PID, LTT_FIELD_NAME, LTT_FIELD_TYPE, LTT_FIELD_MODE, LTT_FIELD_SUBMODE, @@ -3119,31 +3241,37 @@ void lttv_state_add_event_hooks(LttvTracesetState *self) enum_process_state, NULL, &hooks); lttv_trace_find_hook(ts->parent.t, + LTT_FACILITY_LIST, LTT_EVENT_STATEDUMP_END, NULL, statedump_end, NULL, &hooks); lttv_trace_find_hook(ts->parent.t, + LTT_FACILITY_LIST, LTT_EVENT_LIST_INTERRUPT, - FIELD_ARRAY(LTT_FIELD_ACTION, LTT_FIELD_NUM), + FIELD_ARRAY(LTT_FIELD_ACTION, LTT_FIELD_IRQ_ID), enum_interrupt, NULL, &hooks); lttv_trace_find_hook(ts->parent.t, + LTT_FACILITY_BLOCK, LTT_EVENT_REQUEST_ISSUE, FIELD_ARRAY(LTT_FIELD_MAJOR, LTT_FIELD_MINOR, LTT_FIELD_OPERATION), bdev_request_issue, NULL, &hooks); lttv_trace_find_hook(ts->parent.t, + LTT_FACILITY_BLOCK, LTT_EVENT_REQUEST_COMPLETE, FIELD_ARRAY(LTT_FIELD_MAJOR, LTT_FIELD_MINOR, LTT_FIELD_OPERATION), bdev_request_complete, NULL, &hooks); lttv_trace_find_hook(ts->parent.t, + LTT_FACILITY_USER_GENERIC, LTT_EVENT_FUNCTION_ENTRY, FIELD_ARRAY(LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE), function_entry, NULL, &hooks); lttv_trace_find_hook(ts->parent.t, + LTT_FACILITY_USER_GENERIC, LTT_EVENT_FUNCTION_EXIT, FIELD_ARRAY(LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE), function_exit, NULL, &hooks); @@ -3766,8 +3894,8 @@ lttv_tracefile_state_get_type(void) static void module_init() { - LTTV_STATE_UNNAMED = g_quark_from_string("UNNAMED"); - LTTV_STATE_UNBRANDED = g_quark_from_string("UNBRANDED"); + LTTV_STATE_UNNAMED = g_quark_from_string(""); + LTTV_STATE_UNBRANDED = g_quark_from_string(""); LTTV_STATE_MODE_UNKNOWN = g_quark_from_string("MODE_UNKNOWN"); LTTV_STATE_USER_MODE = g_quark_from_string("USER_MODE"); LTTV_STATE_SYSCALL = g_quark_from_string("SYSCALL"); @@ -3798,7 +3926,9 @@ static void module_init() LTTV_STATE_TRACE_STATE_USE_COUNT = g_quark_from_string("trace_state_use_count"); LTTV_STATE_RESOURCE_CPUS = g_quark_from_string("cpu resource states"); + LTTV_STATE_RESOURCE_CPUS = g_quark_from_string("cpu count"); LTTV_STATE_RESOURCE_IRQS = g_quark_from_string("irq resource states"); + LTTV_STATE_RESOURCE_SOFT_IRQS = g_quark_from_string("soft irq resource states"); LTTV_STATE_RESOURCE_BLKDEVS = g_quark_from_string("blkdevs resource states"); @@ -3816,8 +3946,8 @@ static void module_init() LTT_EVENT_TRAP_EXIT = g_quark_from_string("trap_exit"); LTT_EVENT_IRQ_ENTRY = g_quark_from_string("irq_entry"); LTT_EVENT_IRQ_EXIT = g_quark_from_string("irq_exit"); - LTT_EVENT_SOFT_IRQ_ENTRY = g_quark_from_string("soft_irq_entry"); - LTT_EVENT_SOFT_IRQ_EXIT = g_quark_from_string("soft_irq_exit"); + LTT_EVENT_SOFT_IRQ_ENTRY = g_quark_from_string("softirq_entry"); + LTT_EVENT_SOFT_IRQ_EXIT = g_quark_from_string("softirq_exit"); LTT_EVENT_SCHED_SCHEDULE = g_quark_from_string("sched_schedule"); LTT_EVENT_PROCESS_FORK = g_quark_from_string("process_fork"); LTT_EVENT_KTHREAD_CREATE = g_quark_from_string("kthread_create"); @@ -3858,12 +3988,12 @@ static void module_init() LTT_FIELD_MINOR = g_quark_from_string("minor"); LTT_FIELD_OPERATION = g_quark_from_string("direction"); LTT_FIELD_ACTION = g_quark_from_string("action"); - LTT_FIELD_NUM = g_quark_from_string("num"); LTTV_CPU_UNKNOWN = g_quark_from_string("unknown"); LTTV_CPU_IDLE = g_quark_from_string("idle"); LTTV_CPU_BUSY = g_quark_from_string("busy"); LTTV_CPU_IRQ = g_quark_from_string("irq"); + LTTV_CPU_SOFT_IRQ = g_quark_from_string("softirq"); LTTV_CPU_TRAP = g_quark_from_string("trap"); LTTV_IRQ_UNKNOWN = g_quark_from_string("unknown");