resourceview: fix stuck irq problem
[lttv.git] / trunk / lttv / lttv / lttv / state.c
index a3c6c9f14e2f6b011654d4a43676651322ba6299..69497d37c681adc9031e50836698dc31653330e3 100644 (file)
@@ -227,6 +227,23 @@ static void bdevstate_free_cb(gpointer key, gpointer value, gpointer user_data);
 static LttvBdevState *bdevstate_copy(LttvBdevState *bds);
 
 
+#if (__SIZEOF_LONG__ == 4)
+guint guint64_hash(gconstpointer key)
+{
+       guint64 ukey = *(const guint64 *)key;
+
+       return (guint)ukey ^ (guint)(ukey >> 32);
+}
+
+gboolean guint64_equal(gconstpointer a, gconstpointer b)
+{
+       guint64 ua = *(const guint64 *)a;
+       guint64 ub = *(const guint64 *)b;
+
+       return ua == ub;
+}
+#endif
+
 void lttv_state_save(LttvTraceState *self, LttvAttribute *container)
 {
   LTTV_TRACE_STATE_GET_CLASS(self)->state_save(self, container);
@@ -328,8 +345,14 @@ static void expand_syscall_table(LttvTraceState *ts, int id)
 
 static void expand_kprobe_table(LttvTraceState *ts, guint64 ip, char *symbol)
 {
+#if (__SIZEOF_LONG__ == 4)
+  guint64 *ip_ptr = g_new(guint64, 1);
+  g_hash_table_insert(ts->kprobe_hash, ip_ptr,
+    (gpointer)(glong)g_quark_from_string(symbol));
+#else
   g_hash_table_insert(ts->kprobe_hash, (gpointer)ip,
     (gpointer)(glong)g_quark_from_string(symbol));
+#endif
 }
 
 static void expand_trap_table(LttvTraceState *ts, int id)
@@ -444,7 +467,8 @@ restore_init_state(LttvTraceState *self)
     /* reset cpu states */
     if(self->cpu_states[i].mode_stack->len > 0) {
       g_array_remove_range(self->cpu_states[i].mode_stack, 0, self->cpu_states[i].mode_stack->len);
-      self->cpu_states[i].last_irq = -1;
+      if(self->cpu_states[i].irq_stack->len)
+        g_array_remove_range(self->cpu_states[i].irq_stack, 0, self->cpu_states[i].irq_stack->len);
       self->cpu_states[i].last_soft_irq = -1;
       self->cpu_states[i].last_trap = -1;
     }
@@ -626,7 +650,7 @@ init(LttvTracesetState *self, LttvTraceset *ts)
     tcs->cpu_states = g_new(LttvCPUState, nb_cpu);
     for(j = 0; j<nb_cpu; j++) {
       tcs->cpu_states[j].mode_stack = g_array_new(FALSE, FALSE, sizeof(LttvCPUMode));
-      tcs->cpu_states[j].last_irq = -1;
+      tcs->cpu_states[j].irq_stack = g_array_new(FALSE, FALSE, sizeof(gint));
       tcs->cpu_states[j].last_soft_irq = -1;
       tcs->cpu_states[j].last_trap = -1;
       g_assert(tcs->cpu_states[j].mode_stack != NULL);
@@ -1305,10 +1329,16 @@ static LttvCPUState *lttv_state_copy_cpu_states(LttvCPUState *states, guint n)
   retval = g_new(LttvCPUState, n);
 
   for(i=0; i<n; i++) {
-    retval[i].mode_stack = g_array_new(FALSE, FALSE, sizeof(LttvCPUMode));
-    retval[i].last_irq = states[i].last_irq;
     retval[i].last_soft_irq = states[i].last_soft_irq;
     retval[i].last_trap = states[i].last_trap;
+
+    retval[i].irq_stack = g_array_new(FALSE, FALSE, sizeof(gint));
+    g_array_set_size(retval[i].irq_stack, states[i].irq_stack->len);
+    for(j=0; j<states[i].irq_stack->len; j++) {
+      g_array_index(retval[i].irq_stack, gint, j) = g_array_index(states[i].irq_stack, gint, j);
+    }
+
+    retval[i].mode_stack = g_array_new(FALSE, FALSE, sizeof(LttvCPUMode));
     g_array_set_size(retval[i].mode_stack, states[i].mode_stack->len);
     for(j=0; j<states[i].mode_stack->len; j++) {
       g_array_index(retval[i].mode_stack, GQuark, j) = g_array_index(states[i].mode_stack, GQuark, j);
@@ -1324,6 +1354,7 @@ static void lttv_state_free_cpu_states(LttvCPUState *states, guint n)
 
   for(i=0; i<n; i++) {
     g_array_free(states[i].mode_stack, TRUE);
+    g_array_free(states[i].irq_stack, TRUE);
   }
 
   g_free(states);
@@ -1939,6 +1970,11 @@ create_name_tables(LttvTraceState *tcs)
         LTT_CHANNEL_KERNEL,
         LTT_EVENT_TRAP_ENTRY,
         FIELD_ARRAY(LTT_FIELD_TRAP_ID),
+        NULL, NULL, &hooks) ||
+     !lttv_trace_find_hook(tcs->parent.t,
+        LTT_CHANNEL_KERNEL,
+        LTT_EVENT_PAGE_FAULT_ENTRY,
+        FIELD_ARRAY(LTT_FIELD_TRAP_ID),
         NULL, NULL, &hooks)) {
 
 //    th = lttv_trace_hook_get_first(&th);
@@ -2006,7 +2042,12 @@ create_name_tables(LttvTraceState *tcs)
 
   g_string_free(fe_name, TRUE);
 
+#if (__SIZEOF_LONG__ == 4)
+  name_tables->kprobe_hash = g_hash_table_new_full(guint64_hash, guint64_equal,
+    g_free, NULL);
+#else
   name_tables->kprobe_hash = g_hash_table_new(g_direct_hash, g_direct_equal);
+#endif
 }
 
 
@@ -2532,7 +2573,7 @@ static gboolean irq_entry(void *hook_data, void *call_data)
   cpu_push_mode(s->cpu_state, LTTV_CPU_IRQ);
 
   /* update irq status */
-  s->cpu_state->last_irq = irq;
+  g_array_append_val(s->cpu_state->irq_stack, irq);
   irq_push_mode(&ts->irq_states[irq], LTTV_IRQ_BUSY);
 
   return FALSE;
@@ -2568,8 +2609,11 @@ static gboolean irq_exit(void *hook_data, void *call_data)
   cpu_pop_mode(s->cpu_state);
 
   /* update irq status */
-  if (s->cpu_state->last_irq != -1)
-    irq_pop_mode(&ts->irq_states[s->cpu_state->last_irq]);
+  if (s->cpu_state->irq_stack->len > 0) {
+    gint last = g_array_index(s->cpu_state->irq_stack, gint, s->cpu_state->irq_stack->len-1);
+    g_array_remove_index(s->cpu_state->irq_stack, s->cpu_state->irq_stack->len-1);
+    irq_pop_mode(&ts->irq_states[last]);
+  }
 
   return FALSE;
 }
This page took 0.023743 seconds and 4 git commands to generate.