model: add read-acquire/fence-release support
[c11tester.git] / action.cc
index 57058921d95726fb5c8f305b5316e34a80e6d39d..a90878f73d9edc34148359f127df6886d4574cd8 100644 (file)
--- a/action.cc
+++ b/action.cc
@@ -31,13 +31,14 @@ ModelAction::ModelAction(action_type_t type, memory_order order, void *loc,
        location(loc),
        value(value),
        reads_from(NULL),
+       last_fence_release(NULL),
        node(NULL),
        seq_number(ACTION_INITIAL_CLOCK),
        cv(NULL),
        sleep_flag(false)
 {
        /* References to NULL atomic variables can end up here */
-       ASSERT(loc || type == MODEL_FIXUP_RELSEQ);
+       ASSERT(loc || type == ATOMIC_FENCE || type == MODEL_FIXUP_RELSEQ);
 
        Thread *t = thread ? thread : thread_current();
        this->tid = t->get_id();
@@ -69,6 +70,11 @@ void ModelAction::set_seq_number(modelclock_t num)
        seq_number = num;
 }
 
+bool ModelAction::is_thread_start() const
+{
+       return type == THREAD_START;
+}
+
 bool ModelAction::is_relseq_fixup() const
 {
        return type == MODEL_FIXUP_RELSEQ;
@@ -156,6 +162,11 @@ bool ModelAction::is_initialization() const
        return type == ATOMIC_INIT;
 }
 
+bool ModelAction::is_relaxed() const
+{
+       return order == std::memory_order_relaxed;
+}
+
 bool ModelAction::is_acquire() const
 {
        switch (order) {
@@ -187,6 +198,19 @@ bool ModelAction::is_seqcst() const
 
 bool ModelAction::same_var(const ModelAction *act) const
 {
+       if ( act->is_wait() || is_wait() ) {
+               if ( act->is_wait() && is_wait() ) {
+                       if ( ((void *)value) == ((void *)act->value) )
+                               return true;
+               } else if ( is_wait() ) {
+                       if ( ((void *)value) == act->location )
+                               return true;
+               } else if ( act->is_wait() ) {
+                       if ( location == ((void *)act->value) )
+                               return true;
+               }
+       }
+
        return location == act->location;
 }
 
@@ -235,13 +259,36 @@ bool ModelAction::could_synchronize_with(const ModelAction *act) const
        if (!same_var(act))
                return false;
 
-       // Explore interleavings of seqcst writes to guarantee total order
-       // of seq_cst operations that don't commute
-       if ((could_be_write() || act->could_be_write()) && is_seqcst() && act->is_seqcst())
+       // Explore interleavings of seqcst writes/fences to guarantee total
+       // order of seq_cst operations that don't commute
+       if ((could_be_write() || act->could_be_write() || is_fence() || act->is_fence())
+                       && is_seqcst() && act->is_seqcst())
+               return true;
+
+       // Explore synchronizing read/write/fence pairs
+       if (is_acquire() && act->is_release() && (is_read() || is_fence()) &&
+                       (act->could_be_write() || act->is_fence()))
                return true;
 
-       // Explore synchronizing read/write pairs
-       if (is_read() && is_acquire() && act->could_be_write() && act->is_release())
+       //lock just released...we can grab lock
+       if ((is_lock() ||is_trylock()) && (act->is_unlock()||act->is_wait()))
+               return true;
+
+       //lock just acquired...we can fail to grab lock
+       if (is_trylock() && act->is_success_lock())
+               return true;
+
+       //other thread stalling on lock...we can release lock
+       if (is_unlock() && (act->is_trylock()||act->is_lock()))
+               return true;
+
+       if (is_trylock() && (act->is_unlock()||act->is_wait()))
+               return true;
+
+       if ( is_notify() && act->is_wait() )
+               return true;
+
+       if ( is_wait() && act->is_notify() )
                return true;
 
        // Otherwise handle by reads_from relation
@@ -295,24 +342,10 @@ void ModelAction::set_try_lock(bool obtainedlock) {
 /**
  * Update the model action's read_from action
  * @param act The action to read from; should be a write
- * @return True if this read established synchronization
  */
-bool ModelAction::read_from(const ModelAction *act)
+void ModelAction::set_read_from(const ModelAction *act)
 {
-       ASSERT(cv);
        reads_from = act;
-       if (act != NULL && this->is_acquire()) {
-               rel_heads_list_t release_heads;
-               model->get_release_seq_heads(this, &release_heads);
-               int num_heads = release_heads.size();
-               for (unsigned int i = 0; i < release_heads.size(); i++)
-                       if (!synchronize_with(release_heads[i])) {
-                               model->set_bad_synchronization();
-                               num_heads--;
-                       }
-               return num_heads > 0;
-       }
-       return false;
 }
 
 /**
@@ -331,7 +364,7 @@ bool ModelAction::synchronize_with(const ModelAction *act) {
 
 bool ModelAction::has_synchronized_with(const ModelAction *act) const
 {
-       return cv->has_synchronized_with(act->cv);
+       return cv->synchronized_since(act);
 }
 
 /**
@@ -398,6 +431,15 @@ void ModelAction::print() const
        case ATOMIC_TRYLOCK:
                type_str = "trylock";
                break;
+       case ATOMIC_WAIT:
+               type_str = "wait";
+               break;
+       case ATOMIC_NOTIFY_ONE:
+               type_str = "notify one";
+               break;
+       case ATOMIC_NOTIFY_ALL:
+               type_str = "notify all";
+               break;
        default:
                type_str = "unknown type";
        }
@@ -425,22 +467,22 @@ void ModelAction::print() const
                break;
        }
 
-       printf("(%4d) Thread: %-2d   Action: %-13s   MO: %7s  Loc: %14p   Value: %-#18" PRIx64,
+       model_print("(%4d) Thread: %-2d   Action: %-13s   MO: %7s  Loc: %14p   Value: %-#18" PRIx64,
                        seq_number, id_to_int(tid), type_str, mo_str, location, valuetoprint);
        if (is_read()) {
                if (reads_from)
-                       printf("  Rf: %-3d", reads_from->get_seq_number());
+                       model_print("  Rf: %-3d", reads_from->get_seq_number());
                else
-                       printf("  Rf: ?  ");
+                       model_print("  Rf: ?  ");
        }
        if (cv) {
                if (is_read())
-                       printf(" ");
+                       model_print(" ");
                else
-                       printf("          ");
+                       model_print("          ");
                cv->print();
        } else
-               printf("\n");
+               model_print("\n");
 }
 
 /** @brief Print nicely-formatted info about this ModelAction */
@@ -449,7 +491,7 @@ unsigned int ModelAction::hash() const
        unsigned int hash=(unsigned int) this->type;
        hash^=((unsigned int)this->order)<<3;
        hash^=seq_number<<5;
-       hash^=tid<<6;
+       hash ^= id_to_int(tid) << 6;
 
        if (is_read()) {
                if (reads_from)