Merge branch 'norris'
authorBrian Norris <banorris@uci.edu>
Fri, 14 Sep 2012 18:25:59 +0000 (11:25 -0700)
committerBrian Norris <banorris@uci.edu>
Fri, 14 Sep 2012 18:25:59 +0000 (11:25 -0700)
1  2 
model.cc
model.h

diff --combined model.cc
index cdce1028c141b914dcf4f0d7623df3c452eeb461,c7a71ccdb2f541869ae61bd968e78c1523c35548..954c07dd6dacdfc9473a4aa3f5e0a2f8db38bcbf
+++ b/model.cc
@@@ -21,7 -21,6 +21,7 @@@ ModelChecker::ModelChecker(struct model
        /* Initialize default scheduler */
        scheduler(new Scheduler()),
        num_executions(0),
 +      num_feasible_executions(0),
        params(params),
        diverge(NULL),
        action_trace(new action_list_t()),
@@@ -175,8 -174,6 +175,8 @@@ bool ModelChecker::next_execution(
        DBG();
  
        num_executions++;
 +      if (isfinalfeasible())
 +              num_feasible_executions++;
  
        if (isfinalfeasible() || DBG_ENABLED())
                print_summary();
@@@ -265,11 -262,11 +265,11 @@@ ModelAction * ModelChecker::get_next_ba
  /**
   * Processes a read or rmw model action.
   * @param curr is the read model action to process.
-  * @param th is the thread
   * @param second_part_of_rmw is boolean that is true is this is the second action of a rmw.
   * @return True if processing this read updates the mo_graph.
   */
- bool ModelChecker::process_read(ModelAction *curr, Thread * th, bool second_part_of_rmw) {
+ bool ModelChecker::process_read(ModelAction *curr, bool second_part_of_rmw)
+ {
        uint64_t value;
        bool updated = false;
        while (true) {
                        Promise *valuepromise = new Promise(curr, value, expiration);
                        promises->push_back(valuepromise);
                }
-               th->set_return_value(value);
+               get_thread(curr)->set_return_value(value);
                return updated;
        }
  }
  
+ /**
+  * Process a write ModelAction
+  * @param curr The ModelAction to process
+  * @return True if the mo_graph was updated or promises were resolved
+  */
+ bool ModelChecker::process_write(ModelAction *curr)
+ {
+       bool updated_mod_order = w_modification_order(curr);
+       bool updated_promises = resolve_promises(curr);
+       if (promises->size() == 0) {
+               for (unsigned int i = 0; i<futurevalues->size(); i++) {
+                       struct PendingFutureValue pfv = (*futurevalues)[i];
+                       if (pfv.act->get_node()->add_future_value(pfv.value, pfv.expiration) &&
+                                       (!priv->next_backtrack || *pfv.act > *priv->next_backtrack))
+                               priv->next_backtrack = pfv.act;
+               }
+               futurevalues->resize(0);
+       }
+       mo_graph->commitChanges();
+       get_thread(curr)->set_return_value(VALUE_NONE);
+       return updated_mod_order || updated_promises;
+ }
  /**
   * This is the heart of the model checker routine. It performs model-checking
   * actions corresponding to a given "current action." Among other processes, it
@@@ -395,33 -417,36 +420,36 @@@ Thread * ModelChecker::check_current_ac
                break;
        }
  
-       bool updated = false;
+       work_queue_t work_queue(1, CheckCurrWorkEntry(curr));
  
-       if (curr->is_read()) {
-               updated = process_read(curr, get_thread(curr), second_part_of_rmw);
-       }
+       while (!work_queue.empty()) {
+               WorkQueueEntry work = work_queue.front();
+               work_queue.pop_front();
  
-       if (curr->is_write()) {
-               bool updated_mod_order = w_modification_order(curr);
-               bool updated_promises = resolve_promises(curr);
-               updated = updated || updated_mod_order || updated_promises;
-               if (promises->size()==0) {
-                       for (unsigned int i = 0; i<futurevalues->size(); i++) {
-                               struct PendingFutureValue pfv=(*futurevalues)[i];
-                               if (pfv.act->get_node()->add_future_value(pfv.value, pfv.expiration) &&
-                                               (!priv->next_backtrack || *pfv.act > *priv->next_backtrack))
-                                       priv->next_backtrack = pfv.act;
-                       }
-                       futurevalues->resize(0);
-               }
+               switch (work.type) {
+               case WORK_CHECK_CURR_ACTION: {
+                       ModelAction *act = work.action;
+                       bool updated = false;
+                       if (act->is_read() && process_read(act, second_part_of_rmw))
+                               updated = true;
  
-               mo_graph->commitChanges();
-               get_thread(curr)->set_return_value(VALUE_NONE);
-       }
+                       if (act->is_write() && process_write(act))
+                               updated = true;
  
-       if (updated)
-               resolve_release_sequences(curr->get_location());
+                       if (updated)
+                               work_queue.push_back(CheckRelSeqWorkEntry(act->get_location()));
+                       break;
+               }
+               case WORK_CHECK_RELEASE_SEQ:
+                       resolve_release_sequences(work.location, &work_queue);
+                       break;
+               case WORK_CHECK_MO_EDGES:
+                       /** @todo Perform follow-up mo_graph checks */
+               default:
+                       ASSERT(false);
+                       break;
+               }
+       }
  
        /* Add action to list.  */
        if (!second_part_of_rmw)
@@@ -589,18 -614,7 +617,18 @@@ void ModelChecker::check_recency(ModelA
  }
  
  /**
 - * Updates the mo_graph with the constraints imposed from the current read.
 + * Updates the mo_graph with the constraints imposed from the current
 + * read.  
 + *
 + * Basic idea is the following: Go through each other thread and find
 + * the lastest action that happened before our read.  Two cases:
 + *
 + * (1) The action is a write => that write must either occur before
 + * the write we read from or be the write we read from.
 + *
 + * (2) The action is a read => the write that that action read from
 + * must occur before the write we read from or be the same write.
 + *
   * @param curr The current action. Must be a read.
   * @param rf The action that curr reads from. Must be a write.
   * @return True if modification order edges were added; false otherwise
@@@ -643,22 -657,7 +671,22 @@@ bool ModelChecker::r_modification_order
        return added;
  }
  
 -/** Updates the mo_graph with the constraints imposed from the current read. */
 +/** This method fixes up the modification order when we resolve a
 + *  promises.  The basic problem is that actions that occur after the
 + *  read curr could not property add items to the modification order
 + *  for our read.
 + *  
 + *  So for each thread, we find the earliest item that happens after
 + *  the read curr.  This is the item we have to fix up with additional
 + *  constraints.  If that action is write, we add a MO edge between
 + *  the Action rf and that action.  If the action is a read, we add a
 + *  MO edge between the Action rf, and whatever the read accessed.
 + *
 + * @param curr is the read ModelAction that we are fixing up MO edges for.
 + * @param rf is the write ModelAction that curr reads from.
 + *
 + */
 +
  void ModelChecker::post_r_modification_order(ModelAction *curr, const ModelAction *rf)
  {
        std::vector<action_list_t> *thrd_lists = obj_thrd_map->get_safe_ptr(curr->get_location());
  
  /**
   * Updates the mo_graph with the constraints imposed from the current write.
 + *
 + * Basic idea is the following: Go through each other thread and find
 + * the lastest action that happened before our write.  Two cases:
 + *
 + * (1) The action is a write => that write must occur before
 + * the current write
 + *
 + * (2) The action is a read => the write that that action read from
 + * must occur before the current write.
 + *
 + * This method also handles two other issues:
 + *
 + * (I) Sequential Consistency: Making sure that if the current write is
 + * seq_cst, that it occurs after the previous seq_cst write.
 + *
 + * (II) Sending the write back to non-synchronizing reads.
 + *
   * @param curr The current action. Must be a write.
   * @return True if modification order edges were added; false otherwise
   */
@@@ -954,9 -936,12 +982,12 @@@ void ModelChecker::get_release_seq_head
   *
   * @param location The location/object that should be checked for release
   * sequence resolutions
-  * @return True if any updates occurred (new synchronization, new mo_graph edges)
+  * @param work_queue The work queue to which to add work items as they are
+  * generated
+  * @return True if any updates occurred (new synchronization, new mo_graph
+  * edges)
   */
- bool ModelChecker::resolve_release_sequences(void *location)
+ bool ModelChecker::resolve_release_sequences(void *location, work_queue_t *work_queue)
  {
        std::list<ModelAction *> *list;
        list = lazy_sync_with_release->getptr(location);
                }
  
                if (updated) {
+                       /* Re-check act for mo_graph edges */
+                       work_queue->push_back(MOEdgeWorkEntry(act));
                        /* propagate synchronization to later actions */
                        action_list_t::reverse_iterator it = action_trace->rbegin();
                        while ((*it) != act) {
                                ModelAction *propagate = *it;
-                               if (act->happens_before(propagate))
-                                       /** @todo new mo_graph edges along with
-                                        * this synchronization? */
+                               if (act->happens_before(propagate)) {
                                        propagate->synchronize_with(act);
+                                       /* Re-check 'propagate' for mo_graph edges */
+                                       work_queue->push_back(MOEdgeWorkEntry(propagate));
+                               }
                        }
                }
                if (complete) {
@@@ -1089,11 -1078,7 +1124,11 @@@ bool ModelChecker::resolve_promises(Mod
                        if (read->is_rmw()) {
                                mo_graph->addRMWEdge(write, read);
                        }
 +                      //First fix up the modification order for actions that happened
 +                      //before the read
                        r_modification_order(read, write);
 +                      //Next fix up the modification order for actions that happened
 +                      //after the read.
                        post_r_modification_order(read, write);
                        promises->erase(promises->begin() + promise_index);
                        resolved = true;
@@@ -1232,15 -1217,9 +1267,15 @@@ void ModelChecker::print_summary(
  {
        printf("\n");
        printf("Number of executions: %d\n", num_executions);
 +      printf("Number of feasible executions: %d\n", num_feasible_executions);
        printf("Total nodes created: %d\n", node_stack->get_total_nodes());
  
 +#if SUPPORT_MOD_ORDER_DUMP
        scheduler->print();
 +      char buffername[100];
 +      sprintf(buffername, "exec%u",num_executions);
 +      mo_graph->dumpGraphToFile(buffername);
 +#endif
  
        if (!isfinalfeasible())
                printf("INFEASIBLE EXECUTION!\n");
diff --combined model.h
index 4f1d6eece463e4e0da4e59d8b09816aa4772d6a9,3d3eba78db81ee8a2904c1e14ed37102e4c4a930..4fc32c6db6c2800d2bdf705d7a8b256683968bab
+++ b/model.h
@@@ -17,6 -17,7 +17,7 @@@
  #include "action.h"
  #include "clockvector.h"
  #include "hashtable.h"
+ #include "workqueue.h"
  
  /* Forward declaration */
  class NodeStack;
@@@ -99,7 -100,6 +100,7 @@@ private
        bool has_asserted() {return asserted;}
        void reset_asserted() {asserted=false;}
        int num_executions;
 +      int num_feasible_executions;
        bool promises_expired();
        const model_params params;
  
         */
        void set_current_action(ModelAction *act) { priv->current_action = act; }
        Thread * check_current_action(ModelAction *curr);
-       bool process_read(ModelAction *curr, Thread * th, bool second_part_of_rmw);
+       bool process_read(ModelAction *curr, bool second_part_of_rmw);
+       bool process_write(ModelAction *curr);
  
        bool take_step();
  
        bool w_modification_order(ModelAction *curr);
        bool release_seq_head(const ModelAction *rf,
                        std::vector< const ModelAction *, MyAlloc<const ModelAction *> > *release_heads) const;
-       bool resolve_release_sequences(void *location);
+       bool resolve_release_sequences(void *location, work_queue_t *work_queue);
  
        ModelAction *diverge;