Complete the transfer of deletions of some actions
[c11tester.git] / funcnode.cc
index 63dd382be236d40ec8e74be45186c0acb81947bb..691b2f6924a9f4427f9720f90d439390fb65cb28 100644 (file)
@@ -177,6 +177,7 @@ void FuncNode::update_tree(action_list_t * act_list)
                return;
 
        HashTable<void *, value_set_t *, uintptr_t, 0> * write_history = history->getWriteHistory();
+       HashSet<ModelAction *, uintptr_t, 2> write_actions;
 
        /* build inst_list from act_list for later processing */
        func_inst_list_t inst_list;
@@ -185,19 +186,21 @@ void FuncNode::update_tree(action_list_t * act_list)
        for (sllnode<ModelAction *> * it = act_list->begin();it != NULL;it = it->getNext()) {
                ModelAction * act = it->getVal();
 
-               // Only ATOMIC_RMW or ATOMIC_WRITE may be swapped with their original types,
-               // which are later added to rw_act_list. Therefore, it is safe to only revert
-               // back action types for actions in rw_act_list whose types have been swapped.
+               // Use the original action type and decrement ref count
+               // so that actions may be deleted by Execution::collectActions
                if (act->get_original_type() != ATOMIC_NOP && act->get_swap_flag() == false)
                        act->use_original_type();
 
-               // Remove func_act_ref so that actions can be deleted by Execution::collectActions
-               act->setFuncActRef(NULL);
+               act->decr_read_ref_count();
+
                if (act->is_read()) {
-                       // For every read or rmw actions in this list, the reads_from is not deleted.
+                       // For every read or rmw actions in this list, the reads_from was marked, and not deleted.
                        // So it is safe to call get_reads_from
                        ModelAction * rf = act->get_reads_from();
-                       rf->setFuncActRef(NULL);
+                       if (rf->get_original_type() != ATOMIC_NOP && rf->get_swap_flag() == false)
+                               rf->use_original_type();
+
+                       rf->decr_read_ref_count();
                }
 
                FuncInst * func_inst = get_inst(act);
@@ -242,34 +245,56 @@ void FuncNode::update_tree(action_list_t * act_list)
        update_predicate_tree(&rw_act_list);
 
        // Revert back action types and free
-       for (sllnode<ModelAction *> * it = act_list->begin(); it != NULL; it = it->getNext()) {
+       for (sllnode<ModelAction *> * it = act_list->begin(); it != NULL;) {
                ModelAction * act = it->getVal();
+               // Do iteration early in case we delete read actions
+               it = it->getNext();
+
+               // Collect write actions and reads_froms
+               if (act->is_read()) {
+                       if (act->is_rmw()) {
+                               write_actions.add(act);
+                       }
+
+                       ModelAction * rf = act->get_reads_from();
+                       write_actions.add(rf);
+               } else if (act->is_write()) {
+                       write_actions.add(act);
+               }
+
+               // Revert back action types
+               if (act->is_read()) {
+                       ModelAction * rf = act->get_reads_from();
+                       if (rf->get_swap_flag() == true)
+                               rf->use_original_type();
+               }
 
-               // Revert back action types for actions whose types have been changed. 
                if (act->get_swap_flag() == true)
                        act->use_original_type();
 
-               /**  Free actions
-                * case 1. READY_FREE -> delete
-                * case 2. Read action whose read from is READY_FREE -> delete both actions
-                * In both cases, the actions have already been removed from core model
-                * action lists.
-                */
+               //  Free read actions
+               if (act->is_read()) {
+                       if (act->is_rmw()) {
+                               // Do nothing. Its reads_from can not be READY_FREE
+                       } else {
+                               ModelAction *rf = act->get_reads_from();
+                               if (rf->is_free()) {
+                                       model_print("delete read %d; %p\n", act->get_seq_number(), act);
+                                       delete act;
+                               }
+                       }
+               }
+       }
 
-               /* Problematic: could double free actions
-               if (act->is_free()) {
-                       model_print("delete free act %d\n", act->get_seq_number());
+       // Free write actions if possible
+       HSIterator<ModelAction *, uintptr_t, 2> * it = write_actions.iterator();
+       while (it->hasNext()) {
+               ModelAction * act = it->next();
+
+               if (act->is_free() && act->get_read_ref_count() == 0)
                        delete act;
-               } else if (act->is_read()) {
-                       ModelAction * rf = act->get_reads_from();
-                       if (rf->is_free()) {
-                               model_print("delete act %d\n", act->get_seq_number());
-                               model_print("delete act %d\n", rf->get_seq_number());
-                               delete rf;
-                               delete act;
-                       }
-               }*/
        }
+       delete it;
 
 //     print_predicate_tree();
 }