Improve documentation
[c11tester.git] / execution.cc
index 63c0ac7f23b255858d96e2c5b7f067411b18fa74..b0a12e584c28e6a6ab8c6f3596190eddbb1d08d0 100644 (file)
@@ -1168,11 +1168,11 @@ void ModelExecution::add_action_to_lists(ModelAction *act, bool canprune)
 sllnode<ModelAction *>* insertIntoActionList(action_list_t *list, ModelAction *act) {
        sllnode<ModelAction*> * rit = list->end();
        modelclock_t next_seq = act->get_seq_number();
-       if (rit == NULL || (rit->getVal()->get_seq_number() == next_seq))
+       if (rit == NULL || (rit->getVal()->get_seq_number() <= next_seq))
                return list->add_back(act);
        else {
                for(;rit != NULL;rit=rit->getPrev()) {
-                       if (rit->getVal()->get_seq_number() == next_seq) {
+                       if (rit->getVal()->get_seq_number() <= next_seq) {
                                return list->insertAfter(rit, act);
                        }
                }
@@ -1186,12 +1186,12 @@ sllnode<ModelAction *>* insertIntoActionListAndSetCV(action_list_t *list, ModelA
        if (rit == NULL) {
                act->create_cv(NULL);
                return NULL;
-       } else if (rit->getVal()->get_seq_number() == next_seq) {
+       } else if (rit->getVal()->get_seq_number() <= next_seq) {
                act->create_cv(rit->getVal());
                return list->add_back(act);
        } else {
                for(;rit != NULL;rit=rit->getPrev()) {
-                       if (rit->getVal()->get_seq_number() == next_seq) {
+                       if (rit->getVal()->get_seq_number() <= next_seq) {
                                act->create_cv(rit->getVal());
                                return list->insertAfter(rit, act);
                        }
@@ -1660,6 +1660,8 @@ Thread * ModelExecution::take_step(ModelAction *curr)
        return action_select_next_thread(curr);
 }
 
+/** This method removes references to an Action before we delete it. */
+
 void ModelExecution::removeAction(ModelAction *act) {
        {
                sllnode<ModelAction *> * listref = act->getTraceRef();
@@ -1697,12 +1699,13 @@ void ModelExecution::removeAction(ModelAction *act) {
                        obj_last_sc_map.remove(act->get_location());
                }
 
-
                //Remove from Cyclegraph
                mo_graph->freeAction(act);
        }
 }
 
+/** Computes clock vector that all running threads have already synchronized to.  */
+
 ClockVector * ModelExecution::computeMinimalCV() {
        ClockVector *cvmin = NULL;
        //Thread 0 isn't a real thread, so skip it..
@@ -1720,8 +1723,10 @@ ClockVector * ModelExecution::computeMinimalCV() {
        return cvmin;
 }
 
+
+/** Sometimes we need to remove an action that is the most recent in the thread.  This happens if it is mo before action in other threads.  In that case we need to create a replacement latest ModelAction */
+
 void ModelExecution::fixupLastAct(ModelAction *act) {
-//Create a standin ModelAction
        ModelAction *newact = new ModelAction(ATOMIC_NOP, std::memory_order_seq_cst, get_thread(act->get_tid()));
        newact->set_seq_number(get_next_seq_num());
        newact->create_cv(act);
@@ -1729,10 +1734,11 @@ void ModelExecution::fixupLastAct(ModelAction *act) {
        add_action_to_lists(newact, false);
 }
 
+/** Compute which actions to free.  */
+
 void ModelExecution::collectActions() {
        //Compute minimal clock vector for all live threads
        ClockVector *cvmin = computeMinimalCV();
-       cvmin->print();
        SnapVector<CycleNode *> * queue = new SnapVector<CycleNode *>();
        modelclock_t maxtofree = priv->used_sequence_numbers - params->traceminsize;
 
@@ -1751,6 +1757,8 @@ void ModelExecution::collectActions() {
 
                thread_id_t act_tid = act->get_tid();
                modelclock_t tid_clock = cvmin->getClock(act_tid);
+
+               //Free if it is invisible or we have set a flag to remove visible actions.
                if (actseq <= tid_clock || params->removevisible) {
                        ModelAction * write;
                        if (act->is_write()) {
@@ -1779,6 +1787,9 @@ void ModelExecution::collectActions() {
                        }
                }
        }
+
+       //We may need to remove read actions in the window we don't delete to preserve correctness.
+
        for (sllnode<ModelAction*> * it2 = action_trace.end();it2 != it;) {
                ModelAction *act = it2->getVal();
                //Do iteration early in case we delete the act
@@ -1790,17 +1801,34 @@ void ModelExecution::collectActions() {
                        islastact = !th->is_complete();
                }
 
-               if (act->is_read() && act->get_reads_from()->is_free()) {
-                       if (act->is_rmw()) {
-                               act->set_type(ATOMIC_WRITE);
-                       }
-                       removeAction(act);
-                       if (islastact) {
-                               fixupLastAct(act);
+               if (act->is_read()) {
+                       if (act->get_reads_from()->is_free()) {
+                               if (act->is_rmw()) {
+                                       //Weaken a RMW from a freed store to a write
+                                       act->set_type(ATOMIC_WRITE);
+                               } else {
+                                       removeAction(act);
+                                       if (islastact) {
+                                               fixupLastAct(act);
+                                       }
+                                       delete act;
+                                       continue;
+                               }
                        }
-                       delete act;
+               }
+               //If we don't delete the action, we should remove references to release fences
+
+               const ModelAction *rel_fence =act->get_last_fence_release();
+               if (rel_fence != NULL) {
+                       modelclock_t relfenceseq = rel_fence->get_seq_number();
+                       thread_id_t relfence_tid = rel_fence->get_tid();
+                       modelclock_t tid_clock = cvmin->getClock(relfence_tid);
+                       //Remove references to irrelevant release fences
+                       if (relfenceseq <= tid_clock)
+                               act->set_last_fence_release(NULL);
                }
        }
+       //Now we are in the window of old actions that we remove if possible
        for (;it != NULL;) {
                ModelAction *act = it->getVal();
                //Do iteration early since we may delete node...
@@ -1813,23 +1841,16 @@ void ModelExecution::collectActions() {
                }
 
                if (act->is_read()) {
-                       if (act->is_rmw()) {
-                               act->set_type(ATOMIC_WRITE);
-                       } else if (act->get_reads_from()->is_free()) {
-                               removeAction(act);
-                               if (islastact) {
-                                       fixupLastAct(act);
-                               }
-                               delete act;
-                       } else {
-                               const ModelAction *rel_fence =act->get_last_fence_release();
-                               if (rel_fence != NULL) {
-                                       modelclock_t relfenceseq = rel_fence->get_seq_number();
-                                       thread_id_t relfence_tid = rel_fence->get_tid();
-                                       modelclock_t tid_clock = cvmin->getClock(relfence_tid);
-                                       //Remove references to irrelevant release fences
-                                       if (relfenceseq <= tid_clock)
-                                               act->set_last_fence_release(NULL);
+                       if (act->get_reads_from()->is_free()) {
+                               if (act->is_rmw()) {
+                                       act->set_type(ATOMIC_WRITE);
+                               } else {
+                                       removeAction(act);
+                                       if (islastact) {
+                                               fixupLastAct(act);
+                                       }
+                                       delete act;
+                                       continue;
                                }
                        }
                } else if (act->is_free()) {
@@ -1838,6 +1859,7 @@ void ModelExecution::collectActions() {
                                fixupLastAct(act);
                        }
                        delete act;
+                       continue;
                } else if (act->is_write()) {
                        //Do nothing with write that hasn't been marked to be freed
                } else if (islastact) {
@@ -1861,6 +1883,7 @@ void ModelExecution::collectActions() {
                        if (actseq <= tid_clock) {
                                removeAction(act);
                                delete act;
+                               continue;
                        }
                } else {
                        //need to deal with lock, annotation, wait, notify, thread create, start, join, yield, finish, nops
@@ -1871,16 +1894,31 @@ void ModelExecution::collectActions() {
                                if (lastlock != act) {
                                        removeAction(act);
                                        delete act;
+                                       continue;
                                }
                        } else if (act->is_create()) {
                                if (act->get_thread_operand()->is_complete()) {
                                        removeAction(act);
                                        delete act;
+                                       continue;
                                }
                        } else {
                                removeAction(act);
                                delete act;
+                               continue;
                        }
+
+                       //If we don't delete the action, we should remove references to release fences
+                       const ModelAction *rel_fence =act->get_last_fence_release();
+                       if (rel_fence != NULL) {
+                               modelclock_t relfenceseq = rel_fence->get_seq_number();
+                               thread_id_t relfence_tid = rel_fence->get_tid();
+                               modelclock_t tid_clock = cvmin->getClock(relfence_tid);
+                               //Remove references to irrelevant release fences
+                               if (relfenceseq <= tid_clock)
+                                       act->set_last_fence_release(NULL);
+                       }
+
                }
        }
 
@@ -1888,8 +1926,6 @@ void ModelExecution::collectActions() {
        delete queue;
 }
 
-
-
 Fuzzer * ModelExecution::getFuzzer() {
        return fuzzer;
 }