X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=action.cc;h=0084fd3411cdb57e888b1dcef161eb16a6d1398d;hb=5566833b04fb088b315dcde5148e05a9ea80c2df;hp=893c812a1f39bd33f60a3b97291ffe9a525ae124;hpb=89bcfc74c2999b15984759e5b0eab4a9c46feaf3;p=cdsspec-compiler.git diff --git a/action.cc b/action.cc index 893c812..0084fd3 100644 --- a/action.cc +++ b/action.cc @@ -1,7 +1,7 @@ #include #define __STDC_FORMAT_MACROS #include -#include +#include #include "model.h" #include "action.h" @@ -12,6 +12,12 @@ #define ACTION_INITIAL_CLOCK 0 +/** @brief A special value to represent a successful trylock */ +#define VALUE_TRYSUCCESS 1 + +/** @brief A special value to represent a failed trylock */ +#define VALUE_TRYFAILED 0 + /** * @brief Construct a new ModelAction * @@ -78,6 +84,11 @@ bool ModelAction::is_thread_start() const return type == THREAD_START; } +bool ModelAction::is_thread_join() const +{ + return type == THREAD_JOIN; +} + bool ModelAction::is_relseq_fixup() const { return type == MODEL_FIXUP_RELSEQ; @@ -151,6 +162,11 @@ bool ModelAction::could_be_write() const return is_write() || is_rmwr(); } +bool ModelAction::is_yield() const +{ + return type == THREAD_YIELD; +} + bool ModelAction::is_rmwr() const { return type == ATOMIC_RMWR; @@ -264,11 +280,17 @@ Thread * ModelAction::get_thread_operand() const 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. +/** + * @brief Convert the read portion of an RMW + * + * Changes an existing read part of an RMW action into either: + * -# a full RMW action in case of the completed write or + * -# a READ action in case a failed action. + * * @todo If the memory_order changes, we may potentially need to update our * clock vector. + * + * @param act The second half of the RMW (either RMWC or RMW) */ void ModelAction::process_rmw(ModelAction *act) { @@ -281,14 +303,18 @@ void ModelAction::process_rmw(ModelAction *act) } } -/** The is_synchronizing method should only explore interleavings if: - * (1) the operations are seq_cst and don't commute or - * (2) the reordering may establish or break a synchronization relation. - * Other memory operations will be dealt with by using the reads_from - * relation. +/** + * @brief Check if this action should be backtracked with another, due to + * potential synchronization + * + * The is_synchronizing method should only explore interleavings if: + * -# the operations are seq_cst and don't commute or + * -# the reordering may establish or break a synchronization relation. + * + * Other memory operations will be dealt with by using the reads_from relation. * - * @param act is the action to consider exploring a reordering. - * @return tells whether we have to explore a reordering. + * @param act The action to consider exploring a reordering + * @return True, if we have to explore a reordering; otherwise false */ bool ModelAction::could_synchronize_with(const ModelAction *act) const { @@ -371,11 +397,9 @@ void ModelAction::create_cv(const ModelAction *parent) cv = new ClockVector(NULL, this); } -void ModelAction::set_try_lock(bool obtainedlock) { - if (obtainedlock) - value = VALUE_TRYSUCCESS; - else - value = VALUE_TRYFAILED; +void ModelAction::set_try_lock(bool obtainedlock) +{ + value = obtainedlock ? VALUE_TRYSUCCESS : VALUE_TRYFAILED; } /** @@ -416,6 +440,26 @@ uint64_t ModelAction::get_write_value() const return value; } +/** + * @brief Get the value returned by this action + * + * For atomic reads (including RMW), an operation returns the value it read. + * For atomic writes, an operation returns the value it wrote. For other + * operations, the return value varies (sometimes is a "don't care"), but the + * value is simply stored in the "value" field. + * + * @return This action's return value + */ +uint64_t ModelAction::get_return_value() const +{ + if (is_read()) + return get_reads_from_value(); + else if (is_write()) + return get_write_value(); + else + return value; +} + /** @return The Node associated with this ModelAction */ Node * ModelAction::get_node() const { @@ -456,9 +500,8 @@ void ModelAction::set_read_from_promise(Promise *promise) */ bool ModelAction::synchronize_with(const ModelAction *act) { - if (*this < *act && type != THREAD_JOIN && type != ATOMIC_LOCK) + if (*this < *act) return false; - model->check_promises(act->get_tid(), cv, act->cv); cv->merge(act->cv); return true; } @@ -548,14 +591,6 @@ void ModelAction::print() const type_str = "unknown type"; } - uint64_t valuetoprint; - if (is_read()) - valuetoprint = get_reads_from_value(); - else if (is_write()) - valuetoprint = get_write_value(); - else - valuetoprint = value; - switch (this->order) { case std::memory_order_relaxed: mo_str = "relaxed"; @@ -578,16 +613,16 @@ void ModelAction::print() const } 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); + seq_number, id_to_int(tid), type_str, mo_str, location, get_return_value()); if (is_read()) { if (reads_from) model_print(" Rf: %-3d", reads_from->get_seq_number()); else if (reads_from_promise) { - int idx = model->get_promise_number(reads_from_promise); + int idx = reads_from_promise->get_index(); if (idx >= 0) model_print(" Rf: P%-2d", idx); else - model_print(" RF: P? "); + model_print(" Rf: P? "); } else model_print(" Rf: ? "); } @@ -609,8 +644,13 @@ unsigned int ModelAction::hash() const hash ^= seq_number << 5; hash ^= id_to_int(tid) << 6; - if (is_read() && reads_from) - hash ^= reads_from->get_seq_number(); + if (is_read()) { + if (reads_from) + hash ^= reads_from->get_seq_number(); + else if (reads_from_promise) + hash ^= reads_from_promise->get_index(); + hash ^= get_reads_from_value(); + } return hash; } @@ -639,3 +679,17 @@ bool ModelAction::may_read_from(const Promise *promise) const return true; return false; } + +/** + * Only valid for LOCK, TRY_LOCK, UNLOCK, and WAIT operations. + * @return The mutex operated on by this action, if any; otherwise NULL + */ +std::mutex * ModelAction::get_mutex() const +{ + if (is_trylock() || is_lock() || is_unlock()) + return (std::mutex *)get_location(); + else if (is_wait()) + return (std::mutex *)get_value(); + else + return NULL; +}