race: where possible, use "const void *" for addresses
[model-checker.git] / action.cc
index 44a6d9ad6948c116e3305bd955e204825f01bc96..1387ed15b67c9ac25d7fcba68491bbb72d8ff236 100644 (file)
--- a/action.cc
+++ b/action.cc
@@ -76,7 +76,7 @@ bool ModelAction::is_relseq_fixup() const
 
 bool ModelAction::is_mutex_op() const
 {
-       return type == ATOMIC_LOCK || type == ATOMIC_TRYLOCK || type == ATOMIC_UNLOCK;
+       return type == ATOMIC_LOCK || type == ATOMIC_TRYLOCK || type == ATOMIC_UNLOCK || type == ATOMIC_WAIT || type == ATOMIC_NOTIFY_ONE || type == ATOMIC_NOTIFY_ALL;
 }
 
 bool ModelAction::is_lock() const
@@ -84,6 +84,18 @@ bool ModelAction::is_lock() const
        return type == ATOMIC_LOCK;
 }
 
+bool ModelAction::is_wait() const {
+       return type == ATOMIC_WAIT;
+}
+
+bool ModelAction::is_notify() const {
+       return type==ATOMIC_NOTIFY_ONE || type==ATOMIC_NOTIFY_ALL;
+}
+
+bool ModelAction::is_notify_one() const {
+       return type==ATOMIC_NOTIFY_ONE;
+}
+
 bool ModelAction::is_unlock() const
 {
        return type == ATOMIC_UNLOCK;
@@ -175,6 +187,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;
 }
 
@@ -232,6 +257,27 @@ bool ModelAction::could_synchronize_with(const ModelAction *act) const
        if (is_read() && is_acquire() && act->could_be_write() && act->is_release())
                return true;
 
+       //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
        return false;
 }
@@ -250,6 +296,10 @@ bool ModelAction::is_conflicting_lock(const ModelAction *act) const
        if (act->is_unlock() && is_trylock() && value == VALUE_TRYSUCCESS)
                return true;
 
+       //Try to push a successful trylock past a wait
+       if (act->is_wait() && is_trylock() && value == VALUE_TRYSUCCESS)
+               return true;
+
        return false;
 }
 
@@ -315,7 +365,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);
 }
 
 /**
@@ -382,6 +432,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";
        }
@@ -433,7 +492,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)