X-Git-Url: http://git.lttng.org./?a=blobdiff_plain;f=ltt%2Fbranches%2Fpoly%2Flttv%2Flttv%2Fstate.c;h=e41af4501a9741225765e01775fabeacaa40dc5f;hb=5e29121ace19a4a4ea8685b56de16a624c06811b;hp=0c0a4cbcd1677bf04c86e79b8f513ea0211dbedb;hpb=311b8e398d4d986809fabacdeff0762ad20bb438;p=lttv.git diff --git a/ltt/branches/poly/lttv/lttv/state.c b/ltt/branches/poly/lttv/lttv/state.c index 0c0a4cbc..e41af450 100644 --- a/ltt/branches/poly/lttv/lttv/state.c +++ b/ltt/branches/poly/lttv/lttv/state.c @@ -16,6 +16,7 @@ * MA 02111-1307, USA. */ +#define _GNU_SOURCE #ifdef HAVE_CONFIG_H #include #endif @@ -23,10 +24,8 @@ #include #include #include -#include #include #include -#include #include #include @@ -75,7 +74,8 @@ GQuark LTT_EVENT_FUNCTION_EXIT, LTT_EVENT_THREAD_BRAND, LTT_EVENT_REQUEST_ISSUE, - LTT_EVENT_REQUEST_COMPLETE; + LTT_EVENT_REQUEST_COMPLETE, + LTT_EVENT_LIST_INTERRUPT; /* Fields Quarks */ @@ -102,7 +102,9 @@ GQuark LTT_FIELD_CALL_SITE, LTT_FIELD_MINOR, LTT_FIELD_MAJOR, - LTT_FIELD_OPERATION; + LTT_FIELD_OPERATION, + LTT_FIELD_ACTION, + LTT_FIELD_NUM; LttvExecutionMode LTTV_STATE_MODE_UNKNOWN, @@ -163,7 +165,9 @@ static GQuark LTTV_STATE_HOOKS, LTTV_STATE_NAME_TABLES, LTTV_STATE_TRACE_STATE_USE_COUNT, - LTTV_STATE_RESOURCE_CPUS; + LTTV_STATE_RESOURCE_CPUS, + LTTV_STATE_RESOURCE_IRQS, + LTTV_STATE_RESOURCE_BLKDEVS; static void create_max_time(LttvTraceState *tcs); @@ -184,6 +188,15 @@ static void lttv_state_free_process_table(GHashTable *processes); static void lttv_trace_states_read_raw(LttvTraceState *tcs, FILE *fp, GPtrArray *quarktable); +/* Resource function prototypes */ +static LttvBdevState *get_hashed_bdevstate(LttvTraceState *ts, guint16 devcode); +static LttvBdevState *bdevstate_new(void); +static void bdevstate_free(LttvBdevState *); +static void bdevstate_free_cb(gpointer key, gpointer value, gpointer user_data); +static LttvBdevState *bdevstate_copy(LttvBdevState *bds); +static LttvBdevState *bdev_state_get(LttvTraceState *ts, guint16 devcode); + + void lttv_state_save(LttvTraceState *self, LttvAttribute *container) { LTTV_TRACE_STATE_GET_CLASS(self)->state_save(self, container); @@ -293,10 +306,15 @@ restore_init_state(LttvTraceState *self) g_array_remove_range(self->cpu_states[i].mode_stack, 0, self->cpu_states[i].mode_stack->len); } + /* reset irq states */ for(i=0; iirq_states[i].mode_stack->len > 0) g_array_remove_range(self->irq_states[i].mode_stack, 0, self->irq_states[i].mode_stack->len); } + + /* reset bdev states */ + g_hash_table_foreach(self->bdev_states, bdevstate_free_cb, NULL); + g_hash_table_steal_all(self->bdev_states); #if 0 nb_tracefile = self->parent.tracefiles->len; @@ -338,7 +356,7 @@ state_load_saved_states(LttvTraceState *tcs) { FILE *fp; GPtrArray *quarktable; - char *trace_path; + const char *trace_path; char path[PATH_MAX]; guint count; guint i; @@ -591,7 +609,7 @@ static void write_process_state(gpointer key, gpointer value, } for(i = 0 ; i < process->user_stack->len; i++) { - address = &g_array_index(process->user_stack, guint64, i); + address = g_array_index(process->user_stack, guint64, i); fprintf(fp, " \n", address); } @@ -726,7 +744,7 @@ static void write_process_state_raw(gpointer key, gpointer value, } for(i = 0 ; i < process->user_stack->len; i++) { - address = &g_array_index(process->user_stack, guint64, i); + address = g_array_index(process->user_stack, guint64, i); fputc(HDR_USER_STACK, fp); fwrite(&address, sizeof(address), 1, fp); #if 0 @@ -1060,7 +1078,7 @@ void lttv_trace_states_read_raw(LttvTraceState *tcs, FILE *fp, } while(1); end_loop: *(tcs->max_time_state_recomputed_in_seek) = tcs->parent.time_span.end_time; - restore_init_state(tcs); + restore_init_state(&tcs->parent); lttv_process_trace_seek_time(tcs, ltt_time_zero); return; } @@ -1143,6 +1161,118 @@ static void lttv_state_free_cpu_states(LttvCPUState *states, guint n) g_free(states); } +static LttvIRQState *lttv_state_copy_irq_states(LttvIRQState *states, guint n) +{ + guint i,j; + LttvIRQState *retval; + + retval = g_malloc(n*sizeof(LttvIRQState)); + + for(i=0; ilen); + for(j=0; jlen; j++) { + g_array_index(retval[i].mode_stack, GQuark, j) = g_array_index(states[i].mode_stack, GQuark, j); + } + } + + return retval; +} + +static void lttv_state_free_irq_states(LttvIRQState *states, guint n) +{ + guint i; + + for(i=0; ibdev_states, &devcode_gint); + if(bdev == NULL) { + LttvBdevState *bdevstate = g_malloc(sizeof(LttvBdevState)); + bdevstate->mode_stack = g_array_new(FALSE, FALSE, sizeof(GQuark)); + + gint * key = g_malloc(sizeof(gint)); + *key = devcode; + g_hash_table_insert(ts->bdev_states, key, bdevstate); + + bdev = bdevstate; + } + + return bdev; +} + +static LttvBdevState *bdevstate_new(void) +{ + LttvBdevState *retval; + retval = g_malloc(sizeof(LttvBdevState)); + retval->mode_stack = g_array_new(FALSE, FALSE, sizeof(GQuark)); + + return retval; +} + +static void bdevstate_free(LttvBdevState *bds) +{ + g_array_free(bds->mode_stack, FALSE); + g_free(bds); +} + +static void bdevstate_free_cb(gpointer key, gpointer value, gpointer user_data) +{ + LttvBdevState *bds = (LttvBdevState *) value; + + bdevstate_free(bds); +} + +static LttvBdevState *bdevstate_copy(LttvBdevState *bds) +{ + LttvBdevState *retval; + + retval = bdevstate_new(); + g_array_insert_vals(retval->mode_stack, 0, bds->mode_stack->data, bds->mode_stack->len); + + return retval; +} + +static void insert_and_copy_bdev_state(gpointer k, gpointer v, gpointer u) +{ + GHashTable *ht = (GHashTable *)u; + LttvBdevState *bds = (LttvBdevState *)v; + LttvBdevState *newbds; + + newbds = bdevstate_copy(v); + + g_hash_table_insert(u, k, newbds); +} + +static GHashTable *lttv_state_copy_blkdev_hashtable(GHashTable *ht) +{ + GHashTable *retval; + + retval = g_hash_table_new(g_int_hash, g_int_equal); + + g_hash_table_foreach(ht, insert_and_copy_bdev_state, retval); + + return retval; +} + +/* Free a hashtable and the LttvBdevState structures its values + * point to. */ + +static void lttv_state_free_blkdev_hashtable(GHashTable *ht) +{ + g_hash_table_foreach(ht, bdevstate_free_cb, NULL); + g_hash_table_destroy(ht); +} + /* The saved state for each trace contains a member "processes", which stores a copy of the process table, and a member "tracefiles" with one entry per tracefile. Each tracefile has a "process" member pointing @@ -1151,7 +1281,7 @@ static void lttv_state_free_cpu_states(LttvCPUState *states, guint n) static void state_save(LttvTraceState *self, LttvAttribute *container) { - guint i, nb_tracefile, nb_cpus; + guint i, nb_tracefile, nb_cpus, nb_irqs; LttvTracefileState *tfcs; @@ -1224,16 +1354,33 @@ static void state_save(LttvTraceState *self, LttvAttribute *container) } } - value = lttv_attribute_add(container, LTTV_STATE_RESOURCE_CPUS, - LTTV_POINTER); - guint size = sizeof(LttvCPUState)*nb_cpus; - *(value.v_pointer) = lttv_state_copy_cpu_states(self->cpu_states, nb_cpus); + /* save the cpu state */ + { + guint size = sizeof(LttvCPUState)*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); + } + + /* save the irq state */ + nb_irqs = self->nb_irqs; + { + guint size = sizeof(LttvCPUState)*nb_irqs; + value = lttv_attribute_add(container, LTTV_STATE_RESOURCE_IRQS, + LTTV_POINTER); + *(value.v_pointer) = lttv_state_copy_irq_states(self->irq_states, nb_irqs); + } + + /* save the blkdev states */ + value = lttv_attribute_add(container, LTTV_STATE_RESOURCE_BLKDEVS, + LTTV_POINTER); + *(value.v_pointer) = lttv_state_copy_blkdev_hashtable(self->bdev_states); } static void state_restore(LttvTraceState *self, LttvAttribute *container) { - guint i, nb_tracefile, pid, nb_cpus; + guint i, nb_tracefile, pid, nb_cpus, nb_irqs; LttvTracefileState *tfcs; @@ -1274,8 +1421,6 @@ static void state_restore(LttvTraceState *self, LttvAttribute *container) g_assert(self->running_process[i] != NULL); } - printf("state restore\n"); - nb_tracefile = self->parent.tracefiles->len; //g_tree_destroy(tsc->pqueue); @@ -1287,6 +1432,19 @@ static void state_restore(LttvTraceState *self, LttvAttribute *container) lttv_state_free_cpu_states(self->cpu_states, nb_cpus); self->cpu_states = lttv_state_copy_cpu_states(*(value.v_pointer), nb_cpus); + /* restore 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(self->irq_states, nb_irqs); + self->irq_states = lttv_state_copy_irq_states(*(value.v_pointer), nb_irqs); + + /* restore 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(self->bdev_states); + self->bdev_states = lttv_state_copy_blkdev_hashtable(*(value.v_pointer)); + for(i = 0 ; i < nb_tracefile ; i++) { tfcs = LTTV_TRACEFILE_STATE(g_array_index(self->parent.tracefiles, @@ -1689,7 +1847,7 @@ static void cpu_push_mode(LttvCPUState *cpust, LttvCPUMode state) static void cpu_pop_mode(LttvCPUState *cpust) { - if(cpust->mode_stack->len == 1) + if(cpust->mode_stack->len <= 1) cpu_set_base_mode(cpust, LTTV_CPU_UNKNOWN); else g_array_set_size(cpust->mode_stack, cpust->mode_stack->len - 1); @@ -1710,7 +1868,7 @@ static void bdev_push_mode(LttvBdevState *bdevst, LttvBdevMode state) static void bdev_pop_mode(LttvBdevState *bdevst) { - if(bdevst->mode_stack->len == 1) + if(bdevst->mode_stack->len <= 1) bdev_set_base_mode(bdevst, LTTV_BDEV_UNKNOWN); else g_array_set_size(bdevst->mode_stack, bdevst->mode_stack->len - 1); @@ -1730,7 +1888,7 @@ static void irq_push_mode(LttvIRQState *irqst, LttvIRQMode state) static void irq_pop_mode(LttvIRQState *irqst) { - if(irqst->mode_stack->len == 1) + if(irqst->mode_stack->len <= 1) irq_set_base_mode(irqst, LTTV_IRQ_UNKNOWN); else g_array_set_size(irqst->mode_stack, irqst->mode_stack->len - 1); @@ -2212,25 +2370,24 @@ static gboolean soft_irq_entry(void *hook_data, void *call_data) return FALSE; } -LttvBdevState *bdev_state_get(LttvTraceState *ts, guint16 devcode) +static gboolean enum_interrupt(void *hook_data, void *call_data) { - gint devcode_gint = devcode; - gpointer bdev = g_hash_table_lookup(ts->bdev_states, &devcode_gint); - if(bdev == NULL) { - LttvBdevState *bdevstate = g_malloc(sizeof(LttvBdevState)); - bdevstate->mode_stack = g_array_new(FALSE, FALSE, sizeof(GQuark)); + LttvTracefileState *s = (LttvTracefileState *)call_data; + LttvTraceState *ts = (LttvTraceState *)s->parent.t_context; + LttEvent *e = ltt_tracefile_get_event(s->parent.tf); + guint8 fac_id = ltt_event_facility_id(e); + guint8 ev_id = ltt_event_eventtype_id(e); + LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data; - gint * key = g_malloc(sizeof(gint)); - *key = devcode; - g_hash_table_insert(ts->bdev_states, key, bdevstate); - printf("adding key %u to hash table\n", *key); + GQuark action = g_quark_from_string(ltt_event_get_string(e, thf->f1)); + guint irq = ltt_event_get_long_unsigned(e, thf->f2); - bdev = bdevstate; - } + ts->irq_names[irq] = action; - return bdev; + return FALSE; } + static gboolean bdev_request_issue(void *hook_data, void *call_data) { LttvTracefileState *s = (LttvTracefileState *)call_data; @@ -2246,7 +2403,7 @@ static gboolean bdev_request_issue(void *hook_data, void *call_data) guint16 devcode = MKDEV(major,minor); /* have we seen this block device before? */ - gpointer bdev = bdev_state_get(ts, devcode); + gpointer bdev = get_hashed_bdevstate(ts, devcode); if(oper == 0) bdev_push_mode(bdev, LTTV_BDEV_BUSY_READING); @@ -2269,7 +2426,7 @@ static gboolean bdev_request_complete(void *hook_data, void *call_data) guint16 devcode = MKDEV(major,minor); /* have we seen this block device before? */ - gpointer bdev = bdev_state_get(ts, devcode); + gpointer bdev = get_hashed_bdevstate(ts, devcode); /* update block device */ bdev_pop_mode(bdev); @@ -3036,6 +3193,12 @@ void lttv_state_add_event_hooks(LttvTracesetState *self) statedump_end, NULL, &g_array_index(hooks, LttvTraceHook, hn++)); if(ret) hn--; + ret = lttv_trace_find_hook(ts->parent.t, + LTT_FACILITY_LIST, LTT_EVENT_LIST_INTERRUPT, + LTT_FIELD_ACTION, LTT_FIELD_NUM, 0, + enum_interrupt, NULL, &g_array_index(hooks, LttvTraceHook, hn++)); + if(ret) hn--; + ret = lttv_trace_find_hook(ts->parent.t, LTT_FACILITY_BLOCK, LTT_EVENT_REQUEST_ISSUE, LTT_FIELD_MAJOR, LTT_FIELD_MINOR, LTT_FIELD_OPERATION, @@ -3730,6 +3893,8 @@ 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_IRQS = g_quark_from_string("irq resource states"); + LTTV_STATE_RESOURCE_BLKDEVS = g_quark_from_string("blkdevs resource states"); LTT_FACILITY_KERNEL = g_quark_from_string("kernel"); @@ -3761,6 +3926,7 @@ static void module_init() LTT_EVENT_THREAD_BRAND = g_quark_from_string("thread_brand"); LTT_EVENT_REQUEST_ISSUE = g_quark_from_string("_blk_request_issue"); LTT_EVENT_REQUEST_COMPLETE = g_quark_from_string("_blk_request_complete"); + LTT_EVENT_LIST_INTERRUPT = g_quark_from_string("interrupt");; LTT_FIELD_SYSCALL_ID = g_quark_from_string("syscall_id"); @@ -3786,6 +3952,8 @@ static void module_init() LTT_FIELD_MAJOR = g_quark_from_string("major"); 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");