bool ModelAction::is_read() const
{
- return type == ATOMIC_READ;
+ return type == ATOMIC_READ || type == ATOMIC_RMW;
}
bool ModelAction::is_write() const
{
- return type == ATOMIC_WRITE || type == ATOMIC_INIT;
+ return type == ATOMIC_WRITE || type == ATOMIC_RMW || type == ATOMIC_INIT;
}
bool ModelAction::is_rmw() const
return tid == act->tid;
}
+void ModelAction::upgrade_rmw(ModelAction * act) {
+ ASSERT(is_read());
+ ASSERT(act->is_rmw());
+ //Upgrade our type to the act's type
+ this->type=act->type;
+ this->order=act->order;
+ this->value=act->value;
+}
+
/** 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.
if (act->is_release() && this->is_acquire())
cv->merge(act->cv);
reads_from = act;
- value = act->value;
}
/**
type_str = "unknown type";
}
+ uint64_t valuetoprint=type==ATOMIC_READ?reads_from->value:value;
+
printf("(%3d) Thread: %-2d Action: %-13s MO: %d Loc: %14p Value: %-12" PRIu64,
- seq_number, id_to_int(tid), type_str, order, location, value);
+ seq_number, id_to_int(tid), type_str, order, location, valuetoprint);
if (reads_from)
printf(" Rf: %d", reads_from->get_seq_number());
if (cv) {
return get_seq_number() > act.get_seq_number();
}
+ void upgrade_rmw(ModelAction * act);
+
MEMALLOC
private:
/** The thread id that performed this action. */
thread_id_t tid;
- /** The value read or written (if RMW, then the value written). This
- * should probably be something longer. */
+ /** The value written (for write or RMW; undefined for read) */
uint64_t value;
/** The action that this action reads from. Only valid for reads */
return;
}
+ if (curr->is_rmw()) {
+ //We have a RMW action
+ process_rmw(curr);
+ //Force the current thread to continue since the RMW should be atomic
+ nextThread = thread_current()->get_id();
+ delete curr;
+ return;
+ }
+
tmp = node_stack->explore_action(curr);
if (tmp) {
/* Discard duplicate ModelAction; use action from NodeStack */
th->set_creation(curr);
}
+ /* Is there a better interface for setting the next thread rather
+ than this field/convoluted approach? Perhaps like just returning
+ it or something? */
+
nextThread = get_next_replay_thread();
Node *currnode = curr->get_node();
return !cyclegraph->checkForCycles();
}
+/** Process a RMW by converting previous read into a RMW. */
+void ModelChecker::process_rmw(ModelAction * act) {
+ int tid = id_to_int(act->get_tid());
+ std::vector<action_list_t> *vec = &(*obj_thrd_map)[act->get_location()];
+ ASSERT(tid < (int) vec->size());
+ ModelAction *lastread=(*vec)[tid].back();
+ lastread->upgrade_rmw(act);
+}
+
void ModelChecker::r_modification_order(ModelAction * curr, const ModelAction *rf) {
std::vector<action_list_t> *thrd_lists = &(*obj_thrd_map)[curr->get_location()];
unsigned int i;
ModelAction * get_parent_action(thread_id_t tid);
ModelAction * get_last_seq_cst(const void *location);
void build_reads_from_past(ModelAction *curr);
+ void process_rmw(ModelAction * curr);
void r_modification_order(ModelAction * curr, const ModelAction *rf);
void w_modification_order(ModelAction * curr);