X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=action.cc;h=317c6a7cd87d9a94fbb695ecb95615ed5bae5613;hb=82df62c2b0805848b87bb71df5b66a4a66f8e25d;hp=a11467587901f258a03b9e11623403f60f3d1263;hpb=cb9bcfa58847b8261c41890d517918260d409bdd;p=c11tester.git diff --git a/action.cc b/action.cc index a1146758..317c6a7c 100644 --- a/action.cc +++ b/action.cc @@ -31,6 +31,7 @@ ModelAction::ModelAction(action_type_t type, memory_order order, void *loc, location(loc), value(value), reads_from(NULL), + reads_from_promise(NULL), last_fence_release(NULL), node(NULL), seq_number(ACTION_INITIAL_CLOCK), @@ -97,11 +98,11 @@ bool ModelAction::is_wait() const { } bool ModelAction::is_notify() const { - return type==ATOMIC_NOTIFY_ONE || type==ATOMIC_NOTIFY_ALL; + return type == ATOMIC_NOTIFY_ONE || type == ATOMIC_NOTIFY_ALL; } bool ModelAction::is_notify_one() const { - return type==ATOMIC_NOTIFY_ONE; + return type == ATOMIC_NOTIFY_ONE; } bool ModelAction::is_unlock() const @@ -165,7 +166,7 @@ bool ModelAction::is_rmwc() const return type == ATOMIC_RMWC; } -bool ModelAction::is_fence() const +bool ModelAction::is_fence() const { return type == ATOMIC_FENCE; } @@ -206,20 +207,20 @@ bool ModelAction::is_release() const bool ModelAction::is_seqcst() const { - return order==std::memory_order_seq_cst; + return order == std::memory_order_seq_cst; } 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) ) + 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 ) + } else if (is_wait()) { + if (((void *)value) == act->location) return true; - } else if ( act->is_wait() ) { - if ( location == ((void *)act->value) ) + } else if (act->is_wait()) { + if (location == ((void *)act->value)) return true; } } @@ -232,24 +233,51 @@ bool ModelAction::same_thread(const ModelAction *act) const return tid == act->tid; } -void ModelAction::copy_typeandorder(ModelAction * act) { +void ModelAction::copy_typeandorder(ModelAction * act) +{ this->type = act->type; this->order = act->order; } +/** + * Get the Thread which is the operand of this action. This is only valid for + * THREAD_* operations (currently only for THREAD_CREATE and THREAD_JOIN). Note + * that this provides a central place for determining the conventions of Thread + * storage in ModelAction, where we generally aren't very type-safe (e.g., we + * store object references in a (void *) address. + * + * For THREAD_CREATE, this yields the Thread which is created. + * For THREAD_JOIN, this yields the Thread we are joining with. + * + * @return The Thread which this action acts on, if exists; otherwise NULL + */ +Thread * ModelAction::get_thread_operand() const +{ + if (type == THREAD_CREATE) { + /* THREAD_CREATE stores its (Thread *) in a thrd_t::priv */ + thrd_t *thrd = (thrd_t *)get_location(); + return thrd->priv; + } else if (type == THREAD_JOIN) + /* THREAD_JOIN uses (Thread *) for location */ + return (Thread *)get_location(); + else + return NULL; +} + /** This method changes an existing read part of an RMW action into either: * (1) a full RMW action in case of the completed write or * (2) a READ action in case a failed action. * @todo If the memory_order changes, we may potentially need to update our * clock vector. */ -void ModelAction::process_rmw(ModelAction * act) { - this->order=act->order; +void ModelAction::process_rmw(ModelAction *act) +{ + this->order = act->order; if (act->is_rmwc()) - this->type=ATOMIC_READ; + this->type = ATOMIC_READ; else if (act->is_rmw()) { - this->type=ATOMIC_RMW; - this->value=act->value; + this->type = ATOMIC_RMW; + this->value = act->value; } } @@ -272,19 +300,17 @@ bool ModelAction::could_synchronize_with(const ModelAction *act) const if (!same_var(act)) return false; - // Explore interleavings of seqcst writes/fences to guarantee total + // 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_fence() || act->is_fence()) - && is_seqcst() && act->is_seqcst()) + if ((could_be_write() || act->could_be_write()) && 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())) + // Explore synchronizing read/write pairs + if (is_acquire() && act->is_release() && is_read() && act->could_be_write()) return true; // lock just released...we can grab lock - if ((is_lock() ||is_trylock()) && (act->is_unlock()||act->is_wait())) + if ((is_lock() || is_trylock()) && (act->is_unlock() || act->is_wait())) return true; // lock just acquired...we can fail to grab lock @@ -292,16 +318,16 @@ bool ModelAction::could_synchronize_with(const ModelAction *act) const return true; // other thread stalling on lock...we can release lock - if (is_unlock() && (act->is_trylock()||act->is_lock())) + if (is_unlock() && (act->is_trylock() || act->is_lock())) return true; - if (is_trylock() && (act->is_unlock()||act->is_wait())) + if (is_trylock() && (act->is_unlock() || act->is_wait())) return true; - if ( is_notify() && act->is_wait() ) + if (is_notify() && act->is_wait()) return true; - if ( is_wait() && act->is_notify() ) + if (is_wait() && act->is_notify()) return true; // Otherwise handle by reads_from relation @@ -313,11 +339,11 @@ bool ModelAction::is_conflicting_lock(const ModelAction *act) const // Must be different threads to reorder if (same_thread(act)) return false; - + // Try to reorder a lock past a successful lock if (act->is_success_lock()) return true; - + // Try to push a successful trylock past an unlock if (act->is_unlock() && is_trylock() && value == VALUE_TRYSUCCESS) return true; @@ -347,9 +373,9 @@ void ModelAction::create_cv(const ModelAction *parent) void ModelAction::set_try_lock(bool obtainedlock) { if (obtainedlock) - value=VALUE_TRYSUCCESS; + value = VALUE_TRYSUCCESS; else - value=VALUE_TRYFAILED; + value = VALUE_TRYFAILED; } /** @return The Node associated with this ModelAction */ @@ -367,17 +393,30 @@ Node * ModelAction::get_node() const void ModelAction::set_read_from(const ModelAction *act) { reads_from = act; + reads_from_promise = NULL; if (act && act->is_uninitialized()) model->assert_bug("May read from uninitialized atomic\n"); } +/** + * Set this action's read-from promise + * @param promise The promise to read from + */ +void ModelAction::set_read_from_promise(const Promise *promise) +{ + ASSERT(is_read()); + reads_from_promise = promise; + reads_from = NULL; +} + /** * Synchronize the current thread with the thread corresponding to the * ModelAction parameter. * @param act The ModelAction to synchronize with * @return True if this is a valid synchronization; false otherwise */ -bool ModelAction::synchronize_with(const ModelAction *act) { +bool ModelAction::synchronize_with(const ModelAction *act) +{ if (*this < *act && type != THREAD_JOIN && type != ATOMIC_LOCK) return false; model->check_promises(act->get_tid(), cv, act->cv); @@ -471,8 +510,10 @@ void ModelAction::print() const } uint64_t valuetoprint; - if (type == ATOMIC_READ && reads_from != NULL) + if (is_read() && reads_from) valuetoprint = reads_from->value; + else if (is_read() && reads_from_promise) + valuetoprint = reads_from_promise->get_value(); else valuetoprint = value; @@ -515,17 +556,15 @@ void ModelAction::print() const model_print("\n"); } -/** @brief Print nicely-formatted info about this ModelAction */ +/** @brief Get a (likely) unique hash for this ModelAction */ unsigned int ModelAction::hash() const { - unsigned int hash=(unsigned int) this->type; - hash^=((unsigned int)this->order)<<3; - hash^=seq_number<<5; + unsigned int hash = (unsigned int)this->type; + hash ^= ((unsigned int)this->order) << 3; + hash ^= seq_number << 5; hash ^= id_to_int(tid) << 6; - if (is_read()) { - if (reads_from) - hash^=reads_from->get_seq_number(); - } + if (is_read() && reads_from) + hash ^= reads_from->get_seq_number(); return hash; }