More code towards freeing old actions
[c11tester.git] / execution.cc
index e4c05cfcf1764ad7d62a2b7a90524282f9e01908..5aaabbcf00060a1ffe55cb77ad11f049037d7648 100644 (file)
@@ -281,7 +281,7 @@ ModelAction * ModelExecution::convertNonAtomicStore(void * location) {
  */
 bool ModelExecution::process_read(ModelAction *curr, SnapVector<ModelAction *> * rf_set)
 {
-       SnapVector<const ModelAction *> * priorset = new SnapVector<const ModelAction *>();
+       SnapVector<ModelAction *> * priorset = new SnapVector<ModelAction *>();
        bool hasnonatomicstore = hasNonAtomicStore(curr->get_location());
        if (hasnonatomicstore) {
                ModelAction * nonatomicstore = convertNonAtomicStore(curr->get_location());
@@ -774,7 +774,7 @@ ModelAction * ModelExecution::process_rmw(ModelAction *act) {
  */
 
 bool ModelExecution::r_modification_order(ModelAction *curr, const ModelAction *rf,
-                                                                                                                                                                       SnapVector<const ModelAction *> * priorset, bool * canprune, bool check_only)
+                                                                                                                                                                       SnapVector<ModelAction *> * priorset, bool * canprune, bool check_only)
 {
        SnapVector<action_list_t> *thrd_lists = obj_thrd_map.get(curr->get_location());
        unsigned int i;
@@ -868,7 +868,7 @@ bool ModelExecution::r_modification_order(ModelAction *curr, const ModelAction *
                                        if (!check_only)
                                                priorset->push_back(act);
                                } else {
-                                       const ModelAction *prevrf = act->get_reads_from();
+                                       ModelAction *prevrf = act->get_reads_from();
                                        if (!prevrf->equals(rf)) {
                                                if (mo_graph->checkReachable(rf, prevrf))
                                                        return false;
@@ -1696,20 +1696,94 @@ ClockVector * ModelExecution::computeMinimalCV() {
 void ModelExecution::collectActions() {
        //Compute minimal clock vector for all live threads
        ClockVector *cvmin = computeMinimalCV();
-
-       //walk action trace...  When we hit an action ,see if it is
+       SnapVector<CycleNode *> * queue = new SnapVector<CycleNode *>();
+       //walk action trace...  When we hit an actionsee if it is
        //invisible (e.g., earlier than the first before the minimum
        //clock for the thread...  if so erase it and all previous
        //actions in cyclegraph
        for (sllnode<ModelAction*>* it = action_trace.begin();it != NULL;it=it->getNext()) {
                ModelAction *act = it->getVal();
+               modelclock_t actseq = act->get_seq_number();
+               thread_id_t act_tid = act->get_tid();
+               modelclock_t tid_clock = cvmin->getClock(act_tid);
+               if (actseq <= tid_clock) {
+                       ModelAction * write;
+                       if (act->is_write()) {
+                               write = act;
+                       } else if (act->is_read()) {
+                               write = act->get_reads_from();
+                       } else
+                               continue;
 
+                       //Mark everything earlier in MO graph to be freed
+                       queue->push_back(mo_graph->getNode_noCreate(write));
+                       while(!queue->empty()) {
+                               CycleNode * node = queue->back();
+                               queue->pop_back();
+                               for(unsigned int i=0;i<node->getNumInEdges();i++) {
+                                       CycleNode * prevnode = node->getInEdge(i);
+                                       ModelAction * prevact = prevnode->getAction();
+                                       if (prevact->get_type() != READY_FREE) {
+                                               prevact->set_free();
+                                               queue->push_back(prevnode);
+                                       }
+                               }
+                       }
+               }
+       }
+       for (sllnode<ModelAction*>* it = action_trace.end();it != NULL;it=it->getPrev()) {
+               ModelAction *act = it->getVal();
+               if (act->is_free()) {
+                       removeAction(act);
+                       delete act;
+               } else if (act->is_read()) {
+                       if (act->get_reads_from()->is_free()) {
+                               removeAction(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);
+                               }
+                       }
+               } else if (act->is_fence()) {
+                       //Note that acquire fences can always be safely
+                       //removed, but could incur extra overheads in
+                       //traversals.  Removing them before the cvmin seems
+                       //like a good compromise.
+
+                       //Release fences before the cvmin don't do anything
+                       //because everyone has already synchronized.
+
+                       //Sequentially fences before cvmin are redundant
+                       //because happens-before will enforce same
+                       //orderings.
+
+                       modelclock_t actseq = act->get_seq_number();
+                       thread_id_t act_tid = act->get_tid();
+                       modelclock_t tid_clock = cvmin->getClock(act_tid);
+                       if (actseq <= tid_clock) {
+                               removeAction(act);
+                               delete act;
+                       }
+               } else {
+                       //need to deal with lock, annotation, wait, notify, thread create, start, join, yield, finish
+                       //lock, notify thread create, thread finish, yield, finish are dead as soon as they are in the trace
+                       //need to keep most recent unlock/wait for each lock
+               }
        }
-
 
        delete cvmin;
+       delete queue;
 }
 
+
+
 Fuzzer * ModelExecution::getFuzzer() {
        return fuzzer;
 }