merge
authorroot <root@plrg-1.ics.uci.edu>
Mon, 16 Dec 2019 23:26:53 +0000 (15:26 -0800)
committerroot <root@plrg-1.ics.uci.edu>
Mon, 16 Dec 2019 23:26:53 +0000 (15:26 -0800)
1  2 
execution.cc
history.cc

diff --combined execution.cc
index 0128f41a0515a3e1c4b8bc7f1c694abba72e0ecc,addaa7afbfc5dc207284799dc22fee6ba8d35657..6286cdef22b05a36729f7946b87c5ca856761eb3
@@@ -129,12 -129,6 +129,12 @@@ modelclock_t ModelExecution::get_next_s
        return ++priv->used_sequence_numbers;
  }
  
 +/** @return a sequence number for a new ModelAction */
 +modelclock_t ModelExecution::get_curr_seq_num()
 +{
 +      return priv->used_sequence_numbers;
 +}
 +
  /** Restore the last used sequence number when actions of a thread are postponed by Fuzzer */
  void ModelExecution::restore_last_seq_num()
  {
@@@ -287,7 -281,7 +287,7 @@@ ModelAction * ModelExecution::convertNo
   */
  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());
        }
  
        // Remove writes that violate read modification order
+       /*
        uint i = 0;
        while (i < rf_set->size()) {
                ModelAction * rf = (*rf_set)[i];
                        rf_set->pop_back();
                } else
                        i++;
-       }
+       }*/
  
        while(true) {
                int index = fuzzer->selectWrite(curr, rf_set);
                        if (canprune && curr->get_type() == ATOMIC_READ) {
                                int tid = id_to_int(curr->get_tid());
                                (*obj_thrd_map.get(curr->get_location()))[tid].pop_back();
 +                              curr->setThrdMapRef(NULL);
                        }
                        return true;
                }
-               ASSERT(false);
-               /* TODO: Following code not needed anymore */
                priorset->clear();
                (*rf_set)[index] = rf_set->back();
                rf_set->pop_back();
@@@ -384,19 -375,18 +382,19 @@@ bool ModelExecution::process_mutex(Mode
                break;
        }
        case ATOMIC_WAIT: {
 -              /* wake up the other threads */
 -              for (unsigned int i = 0;i < get_num_threads();i++) {
 -                      Thread *t = get_thread(int_to_id(i));
 -                      Thread *curr_thrd = get_thread(curr);
 -                      if (t->waiting_on() == curr_thrd && t->get_pending()->is_lock())
 -                              scheduler->wake(t);
 -              }
 +              //TODO: DOESN'T REALLY IMPLEMENT SPURIOUS WAKEUPS CORRECTLY
 +              if (fuzzer->shouldWait(curr)) {
 +                      /* wake up the other threads */
 +                      for (unsigned int i = 0;i < get_num_threads();i++) {
 +                              Thread *t = get_thread(int_to_id(i));
 +                              Thread *curr_thrd = get_thread(curr);
 +                              if (t->waiting_on() == curr_thrd && t->get_pending()->is_lock())
 +                                      scheduler->wake(t);
 +                      }
  
 -              /* unlock the lock - after checking who was waiting on it */
 -              state->locked = NULL;
 +                      /* unlock the lock - after checking who was waiting on it */
 +                      state->locked = NULL;
  
 -              if (fuzzer->shouldWait(curr)) {
                        /* disable this thread */
                        get_safe_ptr_action(&condvar_waiters_map, curr->get_location())->push_back(curr);
                        scheduler->sleep(get_thread(curr));
        }
        case ATOMIC_TIMEDWAIT:
        case ATOMIC_UNLOCK: {
 -              //TODO: FIX WAIT SITUATION...WAITS CAN SPURIOUSLY FAIL...TIMED WAITS SHOULD PROBABLY JUST BE THE SAME AS NORMAL WAITS...THINK ABOUT PROBABILITIES THOUGH....AS IN TIMED WAIT MUST FAIL TO GUARANTEE PROGRESS...NORMAL WAIT MAY FAIL...SO NEED NORMAL WAIT TO WORK CORRECTLY IN THE CASE IT SPURIOUSLY FAILS AND IN THE CASE IT DOESN'T...  TIMED WAITS MUST EVENMTUALLY RELEASE...
 +              //TODO: FIX WAIT SITUATION...WAITS CAN SPURIOUSLY
 +              //FAIL...TIMED WAITS SHOULD PROBABLY JUST BE THE SAME
 +              //AS NORMAL WAITS...THINK ABOUT PROBABILITIES
 +              //THOUGH....AS IN TIMED WAIT MUST FAIL TO GUARANTEE
 +              //PROGRESS...NORMAL WAIT MAY FAIL...SO NEED NORMAL
 +              //WAIT TO WORK CORRECTLY IN THE CASE IT SPURIOUSLY
 +              //FAILS AND IN THE CASE IT DOESN'T...  TIMED WAITS
 +              //MUST EVENMTUALLY RELEASE...
  
                /* wake up the other threads */
                for (unsigned int i = 0;i < get_num_threads();i++) {
@@@ -725,6 -708,10 +723,6 @@@ ModelAction * ModelExecution::check_cur
  
        wake_up_sleeping_actions(curr);
  
 -      /* Add uninitialized actions to lists */
 -      if (!second_part_of_rmw)
 -              add_uninit_action_to_lists(curr);
 -
        SnapVector<ModelAction *> * rf_set = NULL;
        /* Build may_read_from set for newly-created actions */
        if (newly_explored && curr->is_read())
@@@ -788,7 -775,7 +786,7 @@@ ModelAction * ModelExecution::process_r
   */
  
  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;
                                        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;
@@@ -1105,6 -1092,58 +1103,6 @@@ ClockVector * ModelExecution::get_hb_fr
        return vec;
  }
  
 -/**
 - * Performs various bookkeeping operations for the current ModelAction when it is
 - * the first atomic action occurred at its memory location.
 - *
 - * For instance, adds uninitialized action to the per-object, per-thread action vector
 - * and to the action trace list of all thread actions.
 - *
 - * @param act is the ModelAction to process.
 - */
 -void ModelExecution::add_uninit_action_to_lists(ModelAction *act)
 -{
 -      int tid = id_to_int(act->get_tid());
 -      ModelAction *uninit = NULL;
 -      int uninit_id = -1;
 -      SnapVector<action_list_t> *objvec = get_safe_ptr_vect_action(&obj_thrd_map, act->get_location());
 -      if (objvec->empty() && act->is_atomic_var()) {
 -              uninit = get_uninitialized_action(act);
 -              uninit_id = id_to_int(uninit->get_tid());
 -              SnapVector<action_list_t> *vec = get_safe_ptr_vect_action(&obj_wr_thrd_map, act->get_location());
 -              if ((int)vec->size() <= uninit_id) {
 -                      int oldsize = (int) vec->size();
 -                      vec->resize(uninit_id + 1);
 -                      for(int i = oldsize;i < uninit_id + 1;i++) {
 -                              new (&(*vec)[i]) action_list_t();
 -                      }
 -              }
 -              (*vec)[uninit_id].push_front(uninit);
 -      }
 -
 -      // Update action trace, a total order of all actions
 -      if (uninit)
 -              action_trace.push_front(uninit);
 -
 -      // Update obj_thrd_map, a per location, per thread, order of actions
 -      SnapVector<action_list_t> *vec = get_safe_ptr_vect_action(&obj_thrd_map, act->get_location());
 -      if ((int)vec->size() <= tid) {
 -              uint oldsize = vec->size();
 -              vec->resize(priv->next_thread_id);
 -              for(uint i = oldsize;i < priv->next_thread_id;i++)
 -                      new (&(*vec)[i]) action_list_t();
 -      }
 -      if (uninit)
 -              (*vec)[uninit_id].push_front(uninit);
 -
 -      // Update thrd_last_action, the last action taken by each thrad
 -      if ((int)thrd_last_action.size() <= tid)
 -              thrd_last_action.resize(get_num_threads());
 -      if (uninit)
 -              thrd_last_action[uninit_id] = uninit;
 -}
 -
 -
  /**
   * Performs various bookkeeping operations for the current ModelAction. For
   * instance, adds action to the per-object, per-thread action vector and to the
@@@ -1116,13 -1155,12 +1114,13 @@@ void ModelExecution::add_action_to_list
  {
        int tid = id_to_int(act->get_tid());
        if ((act->is_fence() && act->is_seqcst()) || act->is_unlock()) {
 -        action_list_t *list = get_safe_ptr_action(&obj_map, act->get_location());
 -        list->push_back(act);
 +              action_list_t *list = get_safe_ptr_action(&obj_map, act->get_location());
 +              act->setActionRef(list->add_back(act));
        }
  
        // Update action trace, a total order of all actions
 -      action_trace.push_back(act);
 +      act->setTraceRef(action_trace.add_back(act));
 +
  
        // Update obj_thrd_map, a per location, per thread, order of actions
        SnapVector<action_list_t> *vec = get_safe_ptr_vect_action(&obj_thrd_map, act->get_location());
                for(uint i = oldsize;i < priv->next_thread_id;i++)
                        new (&(*vec)[i]) action_list_t();
        }
 -      (*vec)[tid].push_back(act);
 +      act->setThrdMapRef((*vec)[tid].add_back(act));
  
 -      // Update thrd_last_action, the last action taken by each thrad
 +      // Update thrd_last_action, the last action taken by each thread
        if ((int)thrd_last_action.size() <= tid)
                thrd_last_action.resize(get_num_threads());
        thrd_last_action[tid] = act;
  
        if (act->is_wait()) {
                void *mutex_loc = (void *) act->get_value();
 -              get_safe_ptr_action(&obj_map, mutex_loc)->push_back(act);
 +              act->setActionRef(get_safe_ptr_action(&obj_map, mutex_loc)->add_back(act));
  
                SnapVector<action_list_t> *vec = get_safe_ptr_vect_action(&obj_thrd_map, mutex_loc);
                if ((int)vec->size() <= tid) {
                        for(uint i = oldsize;i < priv->next_thread_id;i++)
                                new (&(*vec)[i]) action_list_t();
                }
 -              (*vec)[tid].push_back(act);
 +              act->setThrdMapRef((*vec)[tid].add_back(act));
        }
  }
  
 -void insertIntoActionList(action_list_t *list, ModelAction *act) {
 +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))
 -              list->push_back(act);
 +              return list->add_back(act);
        else {
                for(;rit != NULL;rit=rit->getPrev()) {
                        if (rit->getVal()->get_seq_number() == next_seq) {
 -                              list->insertAfter(rit, act);
 -                              break;
 +                              return list->insertAfter(rit, act);
                        }
                }
 +              return NULL;
        }
  }
  
 -void insertIntoActionListAndSetCV(action_list_t *list, ModelAction *act) {
 +sllnode<ModelAction *>* insertIntoActionListAndSetCV(action_list_t *list, ModelAction *act) {
        sllnode<ModelAction*> * rit = list->end();
        modelclock_t next_seq = act->get_seq_number();
        if (rit == NULL) {
                act->create_cv(NULL);
 +              return NULL;
        } else if (rit->getVal()->get_seq_number() == next_seq) {
                act->create_cv(rit->getVal());
 -              list->push_back(act);
 +              return list->add_back(act);
        } else {
                for(;rit != NULL;rit=rit->getPrev()) {
                        if (rit->getVal()->get_seq_number() == next_seq) {
                                act->create_cv(rit->getVal());
 -                              list->insertAfter(rit, act);
 -                              break;
 +                              return list->insertAfter(rit, act);
                        }
                }
 +              return NULL;
        }
  }
  
  void ModelExecution::add_normal_write_to_lists(ModelAction *act)
  {
        int tid = id_to_int(act->get_tid());
 -      insertIntoActionListAndSetCV(&action_trace, act);
 +      act->setTraceRef(insertIntoActionListAndSetCV(&action_trace, act));
  
        // Update obj_thrd_map, a per location, per thread, order of actions
        SnapVector<action_list_t> *vec = get_safe_ptr_vect_action(&obj_thrd_map, act->get_location());
                for(uint i=oldsize;i<priv->next_thread_id;i++)
                        new (&(*vec)[i]) action_list_t();
        }
 -      insertIntoActionList(&(*vec)[tid],act);
 +      act->setThrdMapRef(insertIntoActionList(&(*vec)[tid],act));
  
 +      ModelAction * lastact = thrd_last_action[tid];
        // Update thrd_last_action, the last action taken by each thrad
 -      if (thrd_last_action[tid]->get_seq_number() == act->get_seq_number())
 +      if (lastact == NULL || lastact->get_seq_number() == act->get_seq_number())
                thrd_last_action[tid] = act;
  }
  
@@@ -1235,7 -1271,7 +1233,7 @@@ void ModelExecution::add_write_to_lists
                for(uint i=oldsize;i<priv->next_thread_id;i++)
                        new (&(*vec)[i]) action_list_t();
        }
 -      (*vec)[tid].push_back(write);
 +      write->setActionRef((*vec)[tid].add_back(write));
  }
  
  /**
@@@ -1395,47 -1431,46 +1393,47 @@@ SnapVector<ModelAction *> *  ModelExecu
        SnapVector<ModelAction *> * rf_set = new SnapVector<ModelAction *>();
  
        /* Iterate over all threads */
 -      for (i = 0;i < thrd_lists->size();i++) {
 -              /* Iterate over actions in thread, starting from most recent */
 -              action_list_t *list = &(*thrd_lists)[i];
 -              sllnode<ModelAction *> * rit;
 -              for (rit = list->end();rit != NULL;rit=rit->getPrev()) {
 -                      ModelAction *act = rit->getVal();
 -
 -                      if (act == curr)
 -                              continue;
 +      if (thrd_lists != NULL)
 +              for (i = 0;i < thrd_lists->size();i++) {
 +                      /* Iterate over actions in thread, starting from most recent */
 +                      action_list_t *list = &(*thrd_lists)[i];
 +                      sllnode<ModelAction *> * rit;
 +                      for (rit = list->end();rit != NULL;rit=rit->getPrev()) {
 +                              ModelAction *act = rit->getVal();
 +
 +                              if (act == curr)
 +                                      continue;
  
 -                      /* Don't consider more than one seq_cst write if we are a seq_cst read. */
 -                      bool allow_read = true;
 -
 -                      if (curr->is_seqcst() && (act->is_seqcst() || (last_sc_write != NULL && act->happens_before(last_sc_write))) && act != last_sc_write)
 -                              allow_read = false;
 -
 -                      /* Need to check whether we will have two RMW reading from the same value */
 -                      if (curr->is_rmwr()) {
 -                              /* It is okay if we have a failing CAS */
 -                              if (!curr->is_rmwrcas() ||
 -                                              valequals(curr->get_value(), act->get_value(), curr->getSize())) {
 -                                      //Need to make sure we aren't the second RMW
 -                                      CycleNode * node = mo_graph->getNode_noCreate(act);
 -                                      if (node != NULL && node->getRMW() != NULL) {
 -                                              //we are the second RMW
 -                                              allow_read = false;
 +                              /* Don't consider more than one seq_cst write if we are a seq_cst read. */
 +                              bool allow_read = true;
 +
 +                              if (curr->is_seqcst() && (act->is_seqcst() || (last_sc_write != NULL && act->happens_before(last_sc_write))) && act != last_sc_write)
 +                                      allow_read = false;
 +
 +                              /* Need to check whether we will have two RMW reading from the same value */
 +                              if (curr->is_rmwr()) {
 +                                      /* It is okay if we have a failing CAS */
 +                                      if (!curr->is_rmwrcas() ||
 +                                                      valequals(curr->get_value(), act->get_value(), curr->getSize())) {
 +                                              //Need to make sure we aren't the second RMW
 +                                              CycleNode * node = mo_graph->getNode_noCreate(act);
 +                                              if (node != NULL && node->getRMW() != NULL) {
 +                                                      //we are the second RMW
 +                                                      allow_read = false;
 +                                              }
                                        }
                                }
 -                      }
  
 -                      if (allow_read) {
 -                              /* Only add feasible reads */
 -                              rf_set->push_back(act);
 -                      }
 +                              if (allow_read) {
 +                                      /* Only add feasible reads */
 +                                      rf_set->push_back(act);
 +                              }
  
 -                      /* Include at most one act per-thread that "happens before" curr */
 -                      if (act->happens_before(curr))
 -                              break;
 +                              /* Include at most one act per-thread that "happens before" curr */
 +                              if (act->happens_before(curr))
 +                                      break;
 +                      }
                }
 -      }
  
        if (DBG_ENABLED()) {
                model_print("Reached read action:\n");
        return rf_set;
  }
  
 -/**
 - * @brief Get an action representing an uninitialized atomic
 - *
 - * This function may create a new one.
 - *
 - * @param curr The current action, which prompts the creation of an UNINIT action
 - * @return A pointer to the UNINIT ModelAction
 - */
 -ModelAction * ModelExecution::get_uninitialized_action(ModelAction *curr) const
 -{
 -      ModelAction *act = curr->get_uninit_action();
 -      if (!act) {
 -              act = new ModelAction(ATOMIC_UNINIT, std::memory_order_relaxed, curr->get_location(), params->uninitvalue, model_thread);
 -              curr->set_uninit_action(act);
 -      }
 -      act->create_cv(NULL);
 -      return act;
 -}
 -
  static void print_list(action_list_t *list)
  {
        sllnode<ModelAction*> *it;
@@@ -1656,174 -1710,6 +1654,174 @@@ Thread * ModelExecution::take_step(Mode
        return action_select_next_thread(curr);
  }
  
 +void ModelExecution::removeAction(ModelAction *act) {
 +      {
 +              sllnode<ModelAction *> * listref = act->getTraceRef();
 +              if (listref != NULL) {
 +                      action_trace.erase(listref);
 +              }
 +      }
 +      {
 +              sllnode<ModelAction *> * listref = act->getThrdMapRef();
 +              if (listref != NULL) {
 +                      SnapVector<action_list_t> *vec = get_safe_ptr_vect_action(&obj_thrd_map, act->get_location());
 +                      (*vec)[act->get_tid()].erase(listref);
 +              }
 +      }
 +      if ((act->is_fence() && act->is_seqcst()) || act->is_unlock()) {
 +              sllnode<ModelAction *> * listref = act->getActionRef();
 +              if (listref != NULL) {
 +                      action_list_t *list = get_safe_ptr_action(&obj_map, act->get_location());
 +                      list->erase(listref);
 +              }
 +      } else if (act->is_wait()) {
 +              sllnode<ModelAction *> * listref = act->getActionRef();
 +              if (listref != NULL) {
 +                      void *mutex_loc = (void *) act->get_value();
 +                      get_safe_ptr_action(&obj_map, mutex_loc)->erase(listref);
 +              }
 +      } else if (act->is_write()) {
 +              sllnode<ModelAction *> * listref = act->getActionRef();
 +              if (listref != NULL) {
 +                      SnapVector<action_list_t> *vec = get_safe_ptr_vect_action(&obj_wr_thrd_map, act->get_location());
 +                      (*vec)[act->get_tid()].erase(listref);
 +              }
 +              //Remove from Cyclegraph
 +              mo_graph->freeAction(act);
 +      }
 +}
 +
 +ClockVector * ModelExecution::computeMinimalCV() {
 +      ClockVector *cvmin = NULL;
 +      for(unsigned int i = 0;i < thread_map.size();i++) {
 +              Thread * t = thread_map[i];
 +              if (t->get_state() == THREAD_COMPLETED)
 +                      continue;
 +              thread_id_t tid = int_to_id(i);
 +              ClockVector * cv = get_cv(tid);
 +              if (cvmin == NULL)
 +                      cvmin = new ClockVector(cv, NULL);
 +              else
 +                      cvmin->minmerge(cv);
 +      }
 +      return cvmin;
 +}
 +
 +//Options...
 +//How often to check for memory
 +//How much of the trace to always keep
 +//Whether to sacrifice completeness...i.e., remove visible writes
 +
 +void ModelExecution::collectActions() {
 +      //Compute minimal clock vector for all live threads
 +      ClockVector *cvmin = computeMinimalCV();
 +      SnapVector<CycleNode *> * queue = new SnapVector<CycleNode *>();
 +      modelclock_t maxtofree = priv->used_sequence_numbers - params->traceminsize;
 +
 +      //Next walk action trace...  When we hit an action, see 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
 +      sllnode<ModelAction*> * it;
 +      for (it = action_trace.begin();it != NULL;it=it->getNext()) {
 +              ModelAction *act = it->getVal();
 +              modelclock_t actseq = act->get_seq_number();
 +
 +              //See if we are done
 +              if (actseq > maxtofree)
 +                      break;
 +
 +              thread_id_t act_tid = act->get_tid();
 +              modelclock_t tid_clock = cvmin->getClock(act_tid);
 +              if (actseq <= tid_clock || params->removevisible) {
 +                      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
 +                      CycleNode * cn = mo_graph->getNode_noCreate(write);
 +                      queue->push_back(cn);
 +                      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 (;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
 +                      if(act->is_unlock() || act->is_wait()) {
 +                              ModelAction * lastlock = get_last_unlock(act);
 +                              if (lastlock != act) {
 +                                      removeAction(act);
 +                                      delete act;
 +                              }
 +                      } else {
 +                              removeAction(act);
 +                              delete act;
 +                      }
 +              }
 +      }
 +
 +      delete cvmin;
 +      delete queue;
 +}
 +
 +
 +
  Fuzzer * ModelExecution::getFuzzer() {
        return fuzzer;
  }
diff --combined history.cc
index d334cb7de10cc3141cd86d5942107155d70ffb9e,e4394a5d68fae99b935d1cdf648281c3956bea1f..6f9fdad4ea7b6b1e3ec06d78261c0e6a0a3604cc
@@@ -385,7 -385,7 +385,7 @@@ WaitObj * ModelHistory::getWaitObj(thre
  }
  
  void ModelHistory::add_waiting_thread(thread_id_t self_id,
 -thread_id_t waiting_for_id, FuncNode * target_node, int dist)
 +                                                                                                                                                      thread_id_t waiting_for_id, FuncNode * target_node, int dist)
  {
        WaitObj * self_wait_obj = getWaitObj(self_id);
        self_wait_obj->add_waiting_for(waiting_for_id, target_node, dist);
@@@ -410,10 -410,11 +410,11 @@@ void ModelHistory::remove_waiting_threa
        }
  
        self_wait_obj->clear_waiting_for();
+       delete iter;
  }
  
  void ModelHistory::stop_waiting_for_node(thread_id_t self_id,
 -thread_id_t waiting_for_id, FuncNode * target_node)
 +                                                                                                                                                               thread_id_t waiting_for_id, FuncNode * target_node)
  {
        WaitObj * self_wait_obj = getWaitObj(self_id);
        bool thread_removed = self_wait_obj->remove_waiting_for_node(waiting_for_id, target_node);
@@@ -503,7 -504,11 +504,11 @@@ void ModelHistory::monitor_waiting_thre
                                stop_waiting_for_node(waited_by_id, tid, target);
                        }
                }
+               delete node_iter;
        }
+       delete tid_iter;
  }
  
  void ModelHistory::monitor_waiting_thread_counter(thread_id_t tid)
                        }
                }
        }
+       delete tid_iter;
  }
  
  /* Reallocate some snapshotted memories when new executions start */