create directories branches, tags, trunk
[lttv.git] / ltt / branches / poly / lttv / lttv / state.c
index ecbf7ec59d4238087c162f83061eb0b40e37a661..6fb3b2afd2d6450a9b8019e65e2ea5506f1737b8 100644 (file)
@@ -65,6 +65,7 @@ GQuark
     LTT_EVENT_TRAP_EXIT,
     LTT_EVENT_IRQ_ENTRY,
     LTT_EVENT_IRQ_EXIT,
+    LTT_EVENT_SOFT_IRQ_RAISE,
     LTT_EVENT_SOFT_IRQ_ENTRY,
     LTT_EVENT_SOFT_IRQ_EXIT,
     LTT_EVENT_SCHED_SCHEDULE,
@@ -268,6 +269,105 @@ gboolean rettrue(gpointer key, gpointer value, gpointer user_data)
        return TRUE;
 }
 
+static guint check_expand(nb, id)
+{
+  if(likely(nb > id))
+    return nb;
+  else
+    return max(id + 1, nb * 2);
+}
+
+static void expand_name_table(LttvTraceState *ts, GQuark **table,
+  guint nb, guint new_nb)
+{
+  /* Expand an incomplete table */
+  GQuark *old_table = *table;
+  *table = g_new(GQuark, new_nb);
+  memcpy(*table, old_table, nb * sizeof(GQuark));
+}
+
+static void fill_name_table(LttvTraceState *ts, GQuark *table, guint nb,
+  guint new_nb, const char *def_string)
+{
+  guint i;
+  GString *fe_name = g_string_new("");
+  for(i = nb; i < new_nb; i++) {
+    g_string_printf(fe_name, "%s %d", def_string, i);
+    table[i] = g_quark_from_string(fe_name->str);
+  }
+  g_string_free(fe_name, TRUE);
+}
+
+static void expand_syscall_table(LttvTraceState *ts, int id)
+{
+  guint new_nb = check_expand(ts->nb_syscalls, id);
+  if(likely(new_nb == ts->nb_syscalls))
+    return;
+  expand_name_table(ts, &ts->syscall_names, ts->nb_syscalls, new_nb);
+  fill_name_table(ts, ts->syscall_names, ts->nb_syscalls, new_nb, "syscall");
+  /* Update the table size */
+  ts->nb_syscalls = new_nb;
+}
+
+static void expand_trap_table(LttvTraceState *ts, int id)
+{
+  guint new_nb = check_expand(ts->nb_traps, id);
+  guint i;
+  if(likely(new_nb == ts->nb_traps))
+    return;
+  expand_name_table(ts, &ts->trap_names, ts->nb_traps, new_nb);
+  fill_name_table(ts, ts->trap_names, ts->nb_traps, new_nb, "trap");
+  /* Update the table size */
+  ts->nb_traps = new_nb;
+
+  LttvTrapState *old_table = ts->trap_states;
+  ts->trap_states = g_new(LttvTrapState, new_nb);
+  memcpy(ts->trap_states, old_table,
+    ts->nb_traps * sizeof(LttvTrapState));
+  for(i = ts->nb_traps; i < new_nb; i++)
+    ts->trap_states[i].running = 0;
+}
+
+static void expand_irq_table(LttvTraceState *ts, int id)
+{
+  guint new_nb = check_expand(ts->nb_irqs, id);
+  guint i;
+  if(likely(new_nb == ts->nb_irqs))
+    return;
+  expand_name_table(ts, &ts->irq_names, ts->nb_irqs, new_nb);
+  fill_name_table(ts, ts->irq_names, ts->nb_irqs, new_nb, "irq");
+
+  LttvIRQState *old_table = ts->irq_states;
+  ts->irq_states = g_new(LttvIRQState, new_nb);
+  memcpy(ts->irq_states, old_table, ts->nb_irqs * sizeof(LttvIRQState));
+  for(i = ts->nb_irqs; i < new_nb; i++) {
+    ts->irq_states[i].mode_stack = g_array_new(FALSE, FALSE, sizeof(LttvIRQMode));
+  }
+
+  /* Update the table size */
+  ts->nb_irqs = new_nb;
+}
+
+static void expand_soft_irq_table(LttvTraceState *ts, int id)
+{
+  guint new_nb = check_expand(ts->nb_soft_irqs, id);
+  guint i;
+  if(likely(new_nb == ts->nb_soft_irqs))
+    return;
+  expand_name_table(ts, &ts->soft_irq_names, ts->nb_soft_irqs, new_nb);
+  fill_name_table(ts, ts->soft_irq_names, ts->nb_soft_irqs, new_nb, "softirq");
+
+  LttvSoftIRQState *old_table = ts->soft_irq_states;
+  ts->soft_irq_states = g_new(LttvSoftIRQState, new_nb);
+  memcpy(ts->soft_irq_states, old_table,
+    ts->nb_soft_irqs * sizeof(LttvSoftIRQState));
+  for(i = ts->nb_soft_irqs; i < new_nb; i++)
+    ts->soft_irq_states[i].running = 0;
+
+  /* Update the table size */
+  ts->nb_soft_irqs = new_nb;
+}
+
 static void
 restore_init_state(LttvTraceState *self)
 {
@@ -331,6 +431,7 @@ restore_init_state(LttvTraceState *self)
 
   /* reset softirq states */
   for(i=0; i<nb_soft_irqs; i++) {
+    self->soft_irq_states[i].pending = 0;
     self->soft_irq_states[i].running = 0;
   }
 
@@ -1171,7 +1272,7 @@ static LttvCPUState *lttv_state_copy_cpu_states(LttvCPUState *states, guint n)
   guint i,j;
   LttvCPUState *retval;
 
-  retval = g_malloc(n*sizeof(LttvCPUState));
+  retval = g_new(LttvCPUState, n);
 
   for(i=0; i<n; i++) {
     retval[i].mode_stack = g_array_new(FALSE, FALSE, sizeof(LttvCPUMode));
@@ -1201,7 +1302,7 @@ static LttvIRQState *lttv_state_copy_irq_states(LttvIRQState *states, guint n)
   guint i,j;
   LttvIRQState *retval;
 
-  retval = g_malloc(n*sizeof(LttvIRQState));
+  retval = g_new(LttvIRQState, n);
 
   for(i=0; i<n; i++) {
     retval[i].mode_stack = g_array_new(FALSE, FALSE, sizeof(LttvIRQMode));
@@ -1230,9 +1331,10 @@ static LttvSoftIRQState *lttv_state_copy_soft_irq_states(LttvSoftIRQState *state
   guint i;
   LttvSoftIRQState *retval;
 
-  retval = g_malloc(n*sizeof(LttvSoftIRQState));
+  retval = g_new(LttvSoftIRQState, n);
 
   for(i=0; i<n; i++) {
+    retval[i].pending = states[i].pending;
     retval[i].running = states[i].running;
   }
 
@@ -1249,7 +1351,7 @@ static LttvTrapState *lttv_state_copy_trap_states(LttvTrapState *states, guint n
   guint i;
   LttvTrapState *retval;
 
-  retval = g_malloc(n*sizeof(LttvTrapState));
+  retval = g_new(LttvTrapState, n);
 
   for(i=0; i<n; i++) {
     retval[i].running = states[i].running;
@@ -1270,10 +1372,10 @@ static LttvBdevState *get_hashed_bdevstate(LttvTraceState *ts, guint16 devcode)
   gint devcode_gint = devcode;
   gpointer bdev = g_hash_table_lookup(ts->bdev_states, &devcode_gint);
   if(bdev == NULL) {
-    LttvBdevState *bdevstate = g_malloc(sizeof(LttvBdevState));
+    LttvBdevState *bdevstate = g_new(LttvBdevState, 1);
     bdevstate->mode_stack = g_array_new(FALSE, FALSE, sizeof(GQuark));
 
-    gint * key = g_malloc(sizeof(gint));
+    gint * key = g_new(gint, 1);
     *key = devcode;
     g_hash_table_insert(ts->bdev_states, key, bdevstate);
 
@@ -1286,7 +1388,7 @@ static LttvBdevState *get_hashed_bdevstate(LttvTraceState *ts, guint16 devcode)
 static LttvBdevState *bdevstate_new(void)
 {
   LttvBdevState *retval;
-  retval = g_malloc(sizeof(LttvBdevState));
+  retval = g_new(LttvBdevState, 1);
   retval->mode_stack = g_array_new(FALSE, FALSE, sizeof(GQuark));
 
   return retval;
@@ -1587,7 +1689,7 @@ static void state_restore(LttvTraceState *self, LttvAttribute *container)
 
 static void state_saved_free(LttvTraceState *self, LttvAttribute *container)
 {
-  guint i, nb_tracefile, nb_cpus, nb_irqs;
+  guint i, nb_tracefile, nb_cpus, nb_irqs, nb_softirqs;
 
   LttvTracefileState *tfcs;
 
@@ -1636,6 +1738,12 @@ static void state_saved_free(LttvTraceState *self, LttvAttribute *container)
   g_assert(type == LTTV_POINTER);
   lttv_state_free_irq_states(*(value.v_pointer), nb_irqs);
 
+  /* free softirq resource states */
+  nb_softirqs = self->nb_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(*(value.v_pointer), nb_softirqs);
+
   /* free the blkdev states */
   type = lttv_attribute_get_by_name(container, LTTV_STATE_RESOURCE_BLKDEVS, &value);
   g_assert(type == LTTV_POINTER);
@@ -2290,28 +2398,10 @@ static gboolean syscall_entry(void *hook_data, void *call_data)
   LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
   LttvTraceHook *th = (LttvTraceHook *)hook_data;
   struct marker_field *f = lttv_trace_get_hook_field(th, 0);
-
   LttvExecutionSubmode submode;
 
-  guint nb_syscalls = ((LttvTraceState *)(s->parent.t_context))->nb_syscalls;
   guint syscall = ltt_event_get_unsigned(e, f);
-  
-  if(nb_syscalls <= syscall) {
-    /* Fixup an incomplete syscall table */
-    GQuark *old_names = ts->syscall_names;
-    guint new_nb_syscalls = max(syscall + 1, ts->nb_syscalls * 2);
-    guint i;
-    GString *fe_name = g_string_new("");
-    ts->syscall_names = g_new(GQuark, new_nb_syscalls);
-    memcpy(ts->syscall_names, old_names,
-        ts->nb_syscalls * sizeof(GQuark));
-    for(i = ts->nb_syscalls ; i < new_nb_syscalls ; i++) {
-      g_string_printf(fe_name, "syscall %d", i);
-      ts->syscall_names[i] = g_quark_from_string(fe_name->str);
-    }
-    g_string_free(fe_name, TRUE);
-    ts->nb_syscalls = new_nb_syscalls;
-  }
+  expand_syscall_table(ts, syscall);
   submode = ((LttvTraceState *)(s->parent.t_context))->syscall_names[syscall];
   /* There can be no system call from PID 0 : unknown state */
   if(process->pid != 0)
@@ -2346,22 +2436,8 @@ static gboolean trap_entry(void *hook_data, void *call_data)
 
   guint64 trap = ltt_event_get_long_unsigned(e, f);
 
-  if (unlikely(ts->nb_traps <= trap)) {
-    /* Fixup an incomplete trap table */
-    GQuark *old_names = ts->trap_names;
-    guint new_nb_traps = max(trap + 1, ts->nb_traps * 2);
-    guint i;
-    GString *fe_name = g_string_new("");
-    ts->trap_names = g_new(GQuark, new_nb_traps);
-    memcpy(ts->trap_names, old_names,
-        ts->nb_traps * sizeof(GQuark));
-    for(i = ts->nb_traps ; i < new_nb_traps ; i++) {
-      g_string_printf(fe_name, "trap %d", i);
-      ts->trap_names[i] = g_quark_from_string(fe_name->str);
-    }
-    g_string_free(fe_name, TRUE);
-    ts->nb_traps = new_nb_traps;
-  }
+  expand_trap_table(ts, trap);
+
   submode = ((LttvTraceState *)(s->parent.t_context))->trap_names[trap];
 
   push_state(s, LTTV_STATE_TRAP, submode);
@@ -2406,22 +2482,8 @@ static gboolean irq_entry(void *hook_data, void *call_data)
   LttvExecutionSubmode submode;
   guint64 irq = ltt_event_get_long_unsigned(e, f);
 
-  if (unlikely(ts->nb_irqs <= irq)) {
-    /* Fixup an incomplete irq table */
-    GQuark *old_names = ts->irq_names;
-    guint new_nb_irqs = max(irq + 1, ts->nb_irqs * 2);
-    guint i;
-    GString *fe_name = g_string_new("");
-    ts->irq_names = g_new(GQuark, new_nb_irqs);
-    memcpy(ts->irq_names, old_names,
-        ts->nb_irqs * sizeof(GQuark));
-    for(i = ts->nb_irqs ; i < new_nb_irqs ; i++) {
-      g_string_printf(fe_name, "irq %d", i);
-      ts->irq_names[i] = g_quark_from_string(fe_name->str);
-    }
-    g_string_free(fe_name, TRUE);
-    ts->nb_irqs = new_nb_irqs;
-  }
+  expand_irq_table(ts, irq);
+
   submode = ((LttvTraceState *)(s->parent.t_context))->irq_names[irq];
 
   /* Do something with the info about being in user or system mode when int? */
@@ -2471,7 +2533,7 @@ static gboolean irq_exit(void *hook_data, void *call_data)
   return FALSE;
 }
 
-static gboolean soft_irq_entry(void *hook_data, void *call_data)
+static gboolean soft_irq_raise(void *hook_data, void *call_data)
 {
   LttvTracefileState *s = (LttvTracefileState *)call_data;
   LttvTraceState *ts = (LttvTraceState *)s->parent.t_context;
@@ -2484,22 +2546,34 @@ static gboolean soft_irq_entry(void *hook_data, void *call_data)
   guint64 softirq = ltt_event_get_long_unsigned(e, f);
   guint64 nb_softirqs = ((LttvTraceState *)(s->parent.t_context))->nb_soft_irqs;
 
-  if (unlikely(nb_softirqs <= softirq)) {
-    /* Fixup an incomplete softirq table */
-    GQuark *old_names = ts->soft_irq_names;
-    guint new_nb_soft_irqs = max(softirq + 1, ts->nb_soft_irqs * 2);
-    guint i;
-    GString *fe_name = g_string_new("");
-    ts->soft_irq_names = g_new(GQuark, new_nb_soft_irqs);
-    memcpy(ts->soft_irq_names, old_names,
-        ts->nb_soft_irqs * sizeof(GQuark));
-    for(i = ts->nb_soft_irqs ; i < new_nb_soft_irqs ; i++) {
-      g_string_printf(fe_name, "softirq %d", i);
-      ts->soft_irq_names[i] = g_quark_from_string(fe_name->str);
-    }
-    g_string_free(fe_name, TRUE);
-    ts->nb_soft_irqs = new_nb_soft_irqs;
+  if(softirq < nb_softirqs) {
+    submode = ((LttvTraceState *)(s->parent.t_context))->soft_irq_names[softirq];
+  } else {
+    /* Fixup an incomplete irq table */
+    GString *string = g_string_new("");
+    g_string_printf(string, "softirq %llu", softirq);
+    submode = g_quark_from_string(string->str);
+    g_string_free(string, TRUE);
   }
+
+  /* update softirq status */
+  /* a soft irq raises are not cumulative */
+  ts->soft_irq_states[softirq].pending=1;
+
+  return FALSE;
+}
+
+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;
+  struct marker_field *f = lttv_trace_get_hook_field(th, 0);
+  LttvExecutionSubmode submode;
+  guint64 softirq = ltt_event_get_long_unsigned(e, f);
+  expand_soft_irq_table(ts, softirq);
   submode = ((LttvTraceState *)(s->parent.t_context))->soft_irq_names[softirq];
 
   /* Do something with the info about being in user or system mode when int? */
@@ -2510,6 +2584,8 @@ static gboolean soft_irq_entry(void *hook_data, void *call_data)
 
   /* update softirq status */
   s->cpu_state->last_soft_irq = softirq;
+  if(ts->soft_irq_states[softirq].pending)
+    ts->soft_irq_states[softirq].pending--;
   ts->soft_irq_states[softirq].running++;
 
   return FALSE;
@@ -2527,21 +2603,7 @@ static gboolean enum_interrupt(void *hook_data, void *call_data)
     lttv_trace_get_hook_field(th, 0)));
   guint irq = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 1));
 
-  if (ts->nb_irqs <= irq) {
-    GQuark *old_names = ts->irq_names;
-    guint new_nb_irqs = max(irq + 1, ts->nb_irqs * 2);
-    guint i;
-    GString *fe_name = g_string_new("");
-    ts->irq_names = g_new(GQuark, new_nb_irqs);
-    memcpy(ts->irq_names, old_names,
-        ts->nb_irqs * sizeof(GQuark));
-    for(i = ts->nb_irqs ; i < new_nb_irqs ; i++) {
-      g_string_printf(fe_name, "irq %d", i);
-      ts->irq_names[i] = g_quark_from_string(fe_name->str);
-    }
-    g_string_free(fe_name, TRUE);
-    ts->nb_irqs = new_nb_irqs;
-  }
+  expand_irq_table(ts, irq);
   ts->irq_names[irq] = action;
 
   return FALSE;
@@ -2691,21 +2753,7 @@ static gboolean dump_syscall(void *hook_data, void *call_data)
   address = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 1));
   symbol = ltt_event_get_string(e, lttv_trace_get_hook_field(th, 2));
 
-  if (ts->nb_syscalls <= id) {
-    GQuark *old_names = ts->syscall_names;
-    guint new_nb_syscalls = max(id + 1, ts->nb_syscalls * 2);
-    guint i;
-    GString *fe_name = g_string_new("");
-    ts->syscall_names = g_new(GQuark, new_nb_syscalls);
-    memcpy(ts->syscall_names, old_names,
-        ts->nb_syscalls * sizeof(GQuark));
-    for(i = ts->nb_syscalls ; i < new_nb_syscalls ; i++) {
-      g_string_printf(fe_name, "syscall %d", i);
-      ts->syscall_names[i] = g_quark_from_string(fe_name->str);
-    }
-    g_string_free(fe_name, TRUE);
-    ts->nb_syscalls = new_nb_syscalls;
-  }
+  expand_syscall_table(ts, id);
   ts->syscall_names[id] = g_quark_from_string(symbol);
 
   return FALSE;
@@ -2725,23 +2773,7 @@ static gboolean dump_softirq(void *hook_data, void *call_data)
   address = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 1));
   symbol = ltt_event_get_string(e, lttv_trace_get_hook_field(th, 2));
 
-  if (ts->nb_soft_irqs <= id) {
-    /* Fixup an incomplete softirq table */
-    GQuark *old_names = ts->soft_irq_names;
-    guint new_nb_soft_irqs = max(id + 1, ts->nb_soft_irqs * 2);
-    guint i;
-    GString *fe_name = g_string_new("");
-    ts->soft_irq_names = g_new(GQuark, new_nb_soft_irqs);
-    memcpy(ts->soft_irq_names, old_names,
-        ts->nb_soft_irqs * sizeof(GQuark));
-    for(i = ts->nb_soft_irqs ; i < new_nb_soft_irqs ; i++) {
-      g_string_printf(fe_name, "softirq %d", i);
-      ts->soft_irq_names[i] = g_quark_from_string(fe_name->str);
-    }
-    g_string_free(fe_name, TRUE);
-    ts->nb_soft_irqs = new_nb_soft_irqs;
-  }
-
+  expand_soft_irq_table(ts, id);
   ts->soft_irq_names[id] = g_quark_from_string(symbol);
 
   return FALSE;
@@ -3370,6 +3402,12 @@ void lttv_state_add_event_hooks(LttvTracesetState *self)
         NULL,
         irq_exit, NULL, &hooks);
 
+    lttv_trace_find_hook(ts->parent.t,
+        LTT_FACILITY_KERNEL,
+        LTT_EVENT_SOFT_IRQ_RAISE,
+        FIELD_ARRAY(LTT_FIELD_SOFT_IRQ_ID),
+        soft_irq_raise, NULL, &hooks);
+
     lttv_trace_find_hook(ts->parent.t,
         LTT_FACILITY_KERNEL,
         LTT_EVENT_SOFT_IRQ_ENTRY,
@@ -4154,6 +4192,7 @@ 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_RAISE     = g_quark_from_string("softirq_raise");
   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");
This page took 0.028004 seconds and 4 git commands to generate.