Events create new tuples and advance existing tuples.
authorJustin Seyster <jseyster@cs.sunysb.edu>
Tue, 15 Feb 2011 03:21:42 +0000 (22:21 -0500)
committerJustin Seyster <jseyster@cs.sunysb.edu>
Wed, 16 Feb 2011 01:21:23 +0000 (20:21 -0500)
src/tracecut-advice.c

index c93304380f61f44f645a0c30cd3524e77b6b92df..6ce00db2e14a4b07f8d88ee85c069c779836bd12 100644 (file)
@@ -8,11 +8,15 @@
 
 static int num_tracecuts = -1;
 
+struct tuple;
+
 struct tracecut {
   int num_params;
   int num_symbols;
 
   const char **symbol_names;
+
+  struct tuple *tuple_list;
 };
 
 static struct tracecut *tracecut_array = NULL;
@@ -32,12 +36,25 @@ struct event {
   int tc_index;
   struct tracecut *tracecut;
 
-  int num_params;
   struct param_val param_vals[];
 };
 
 static struct event *current_event = NULL;
 
+/* Each tracecut object has a list of tuples, with each tuple
+   representing one state machine that the tracecut is tracking.  When
+   an event occurs, the tracecut will update the state machine for
+   every state machine whose params match the non-vacant params in the
+   event. */
+struct tuple {
+  int state;
+
+  /* For now, tuples are stored in a linked list. */
+  struct tuple *next;
+
+  struct param_val param_vals[];
+};
+
 static void
 fatal_tracecut_error(const char *error)
 {
@@ -70,6 +87,116 @@ get_tracecut (int tc_index)
     }
 }
 
+void
+advance_state_machine (struct tuple *tuple, int symbol_index)
+{
+}
+
+int
+event_matches_tuple (struct event *event, struct tuple *tuple)
+{
+  int i;
+  struct tracecut *tc = event->tracecut;
+
+  for (i = 0; i < tc->num_params; i++)
+    {
+      switch (event->param_vals[i].kind)
+       {
+       case PV_VACANT:
+         continue;  /* Vacant values always match. */
+       case PV_POINTER:
+         if (tuple->param_vals[i].kind != PV_POINTER
+             || event->param_vals[i].value != tuple->param_vals[i].value)
+           return 0;  /* Mismatch. */
+         else
+           ;  /* This param matches; keep looking. */
+         break;
+       }
+    }
+
+  /* All param matched! */
+  return 1;
+}
+
+int
+update_matching_tuples (struct event *event)
+{
+  struct tracecut *tc = event->tracecut;
+  struct tuple *tuple;
+  int tuples_updated = 0;
+
+  for (tuple = tc->tuple_list; tuple != NULL; tuple = tuple->next)
+    {
+      if (event_matches_tuple (event, tuple))
+       {
+         advance_state_machine (tuple, event->symbol_index);
+         tuples_updated++;
+         fprintf (stderr, "Advancing existing tuple.\n");
+       }
+    }
+
+  return tuples_updated;
+}
+
+struct tuple *add_tuple_for_event (struct event *event)
+{
+  struct tracecut *tc = event->tracecut;
+  struct tuple *tuple;
+  size_t tuple_size;
+
+  tuple_size = sizeof (struct tuple)
+    + tc->num_params * sizeof (struct param_val);
+  tuple = malloc (tuple_size);
+  if (tuple == NULL)
+    {
+      fatal_tracecut_error ("Out of memory");
+      return NULL;
+    }
+
+  tuple->state = 0;
+  memcpy (tuple->param_vals, event->param_vals,
+         tc->num_params * sizeof (struct param_val));
+
+  /* Insert the tuple into the tracecut's tuple list. */
+  tuple->next = tc->tuple_list;
+  tc->tuple_list = tuple;
+
+  return tuple;
+}
+
+/* An event is "complete" iff only if all its params are specified
+   (i.e., none are vacant). */
+int
+is_event_complete (struct event *event)
+{
+  int i;
+  struct tracecut *tc = event->tracecut;
+
+  for (i = 0; i < tc->num_params; i++)
+    if (event->param_vals[i].kind == PV_VACANT)
+      return 0;
+
+  return 1;
+}
+
+void
+do_transition (struct event *event)
+{
+  int tuples_updated;
+
+  tuples_updated = update_matching_tuples (event);
+
+  if (tuples_updated == 0 && is_event_complete (event))
+    {
+      struct tuple *tuple;
+
+      tuple = add_tuple_for_event (event);
+      if (tuple != NULL)
+       advance_state_machine (tuple, event->symbol_index);
+      fprintf (stderr, "Creating new tuple.\n");
+    }
+}
+
 ADVICE_FUNC void
 _tc_init (int _num_tracecuts)
 {
@@ -148,7 +275,6 @@ _tc_event_begin (int tc_index)
       memset (current_event, 0, event_size);
       current_event->tc_index = tc_index;
       current_event->tracecut = tc;
-      current_event->num_params = tc->num_params;
     }
   else
     {
@@ -169,7 +295,8 @@ _tc_capture_pointer_param (int tc_index, int symbol_index, int param_index,
       fatal_tracecut_error ("Misplaced param value.");
       return;
     }
-  else if (param_index < 0 || param_index >= current_event->num_params)
+  else if (param_index < 0
+          || param_index >= current_event->tracecut->num_params)
     {
       fatal_tracecut_error ("Out-of-bounds param value.");
     }
@@ -190,4 +317,7 @@ _tc_event_transition (int tc_index, int symbol_index)
       fatal_tracecut_error ("Misplaced event transition.");
       return;
     }
+
+  current_event->symbol_index = symbol_index;
+  do_transition (current_event);
 }