X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=action.cc;h=c96949bc906cc02a9ca3cb50af761a92feda94c7;hb=f291abaf7a05ebdc5981072212b55265dafc1c4a;hp=b0d8fc9b7bed4aaacc843cc8620c0abfffc1dd00;hpb=1a75079a60d2788bad4ee82378182abcfade51c8;p=c11tester.git diff --git a/action.cc b/action.cc index b0d8fc9b..c96949bc 100644 --- a/action.cc +++ b/action.cc @@ -5,19 +5,17 @@ #include "clockvector.h" #include "common.h" -ModelAction::ModelAction(action_type_t type, memory_order order, void *loc, int value) +ModelAction::ModelAction(action_type_t type, memory_order order, void *loc, int value) : + type(type), + order(order), + location(loc), + value(value), + reads_from(NULL), + cv(NULL) { Thread *t = thread_current(); - ModelAction *act = this; - - act->type = type; - act->order = order; - act->location = loc; - act->tid = t->get_id(); - act->value = value; - act->seq_number = model->get_next_seq_num(); - - cv = NULL; + this->tid = t->get_id(); + this->seq_number = model->get_next_seq_num(); } ModelAction::~ModelAction() @@ -26,17 +24,27 @@ ModelAction::~ModelAction() delete cv; } -bool ModelAction::is_read() +bool ModelAction::is_read() const { return type == ATOMIC_READ; } -bool ModelAction::is_write() +bool ModelAction::is_write() const +{ + return type == ATOMIC_WRITE || type == ATOMIC_INIT; +} + +bool ModelAction::is_rmw() const { - return type == ATOMIC_WRITE; + return type == ATOMIC_RMW; } -bool ModelAction::is_acquire() +bool ModelAction::is_initialization() const +{ + return type == ATOMIC_INIT; +} + +bool ModelAction::is_acquire() const { switch (order) { case memory_order_acquire: @@ -48,7 +56,7 @@ bool ModelAction::is_acquire() } } -bool ModelAction::is_release() +bool ModelAction::is_release() const { switch (order) { case memory_order_release: @@ -60,46 +68,87 @@ bool ModelAction::is_release() } } -bool ModelAction::same_var(ModelAction *act) +bool ModelAction::is_seqcst() const +{ + return order==memory_order_seq_cst; +} + +bool ModelAction::same_var(const ModelAction *act) const { return location == act->location; } -bool ModelAction::same_thread(ModelAction *act) +bool ModelAction::same_thread(const ModelAction *act) const { return tid == act->tid; } -bool ModelAction::is_dependent(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. + * + * @param act is the action to consider exploring a reordering. + * @return tells whether we have to explore a reordering. + */ + +bool ModelAction::is_synchronizing(const ModelAction *act) const { - if (!is_read() && !is_write()) + //Same thread can't be reordered + if (same_thread(act)) return false; - if (!act->is_read() && !act->is_write()) + + // Different locations commute + if (!same_var(act)) return false; - if (same_var(act) && !same_thread(act) && - (is_write() || act->is_write())) + + // Explore interleavings of seqcst writes to guarantee total order + // of seq_cst operations that don't commute + if (is_write() && is_seqcst() && act->is_write() && act->is_seqcst()) + return true; + + // Explore synchronizing read/write pairs + if (is_read() && is_acquire() && act->is_write() && act->is_release()) return true; + if (is_write() && is_release() && act->is_read() && act->is_acquire()) + return true; + + // Otherwise handle by reads_from relation return false; } -void ModelAction::create_cv(ModelAction *parent) +void ModelAction::create_cv(const ModelAction *parent) { ASSERT(cv == NULL); + if (parent) cv = new ClockVector(parent->cv, this); else - cv = new ClockVector(); + cv = new ClockVector(NULL, this); } -void ModelAction::read_from(ModelAction *act) +void ModelAction::read_from(const ModelAction *act) { ASSERT(cv); if (act->is_release() && this->is_acquire()) cv->merge(act->cv); + reads_from = act; value = act->value; } -void ModelAction::print(void) +/** + * Check whether 'this' happens before act, according to the memory-model's + * happens before relation. This is checked via the ClockVector constructs. + * @return true if this action's thread has synchronized with act's thread + * since the execution of act, false otherwise. + */ +bool ModelAction::happens_before(const ModelAction *act) const +{ + return act->cv->synchronized_since(this); +} + +void ModelAction::print(void) const { const char *type_str; switch (this->type) { @@ -118,10 +167,23 @@ void ModelAction::print(void) case ATOMIC_WRITE: type_str = "atomic write"; break; + case ATOMIC_RMW: + type_str = "atomic rmw"; + break; + case ATOMIC_INIT: + type_str = "init atomic"; + break; default: type_str = "unknown type"; } - printf("(%4d) Thread: %d\tAction: %s\tMO: %d\tLoc: %14p\tValue: %d\n", + printf("(%3d) Thread: %-2d Action: %-13s MO: %d Loc: %14p Value: %-4d", seq_number, id_to_int(tid), type_str, order, location, value); + if (reads_from) + printf(" Rf: %d", reads_from->get_seq_number()); + if (cv) { + printf("\t"); + cv->print(); + } else + printf("\n"); }