}
case READ_FROM_PROMISE: {
Promise *promise = curr->get_node()->get_read_from_promise();
+ promise->add_reader(curr);
value = promise->get_value();
curr->set_read_from_promise(promise);
mo_graph->startChanges();
{
for (unsigned int i = 0; i < promises->size(); i++) {
Promise *promise = (*promises)[i];
- ModelAction *reader = promise->get_action();
- if (reader->get_tid() != blocker->get_id())
- continue;
if (!promise->thread_is_available(waiting->get_id()))
continue;
- if (promise->eliminate_thread(waiting->get_id())) {
- /* Promise has failed */
- priv->failed_promise = true;
+ for (unsigned int j = 0; j < promise->get_num_readers(); j++) {
+ ModelAction *reader = promise->get_reader(j);
+ if (reader->get_tid() != blocker->get_id())
+ continue;
+ if (promise->eliminate_thread(waiting->get_id())) {
+ /* Promise has failed */
+ priv->failed_promise = true;
+ } else {
+ /* Only eliminate the 'waiting' thread once */
+ return;
+ }
}
}
}
for (unsigned int i = 0, promise_index = 0; promise_index < promises->size(); i++) {
Promise *promise = (*promises)[promise_index];
if (write->get_node()->get_promise(i)) {
- ModelAction *read = promise->get_action();
- read_from(read, write);
+ for (unsigned int j = 0; j < promise->get_num_readers(); j++) {
+ ModelAction *read = promise->get_reader(j);
+ read_from(read, write);
+ actions_to_check.push_back(read);
+ }
//Make sure the promise's value matches the write's value
ASSERT(promise->is_compatible(write));
mo_graph->resolvePromise(promise, write, &mustResolve);
resolved.push_back(promise);
promises->erase(promises->begin() + promise_index);
- actions_to_check.push_back(read);
haveResolved = true;
} else
{
for (unsigned int i = 0; i < promises->size(); i++) {
Promise *promise = (*promises)[i];
- const ModelAction *act = promise->get_action();
- ASSERT(act->is_read());
- if (!act->happens_before(curr) &&
- !act->could_synchronize_with(curr) &&
- promise->is_compatible(curr) &&
- promise->get_value() == curr->get_value()) {
- curr->get_node()->set_promise(i);
+ if (!promise->is_compatible(curr) || promise->get_value() != curr->get_value())
+ continue;
+
+ bool satisfy = true;
+ for (unsigned int j = 0; j < promise->get_num_readers(); j++) {
+ const ModelAction *act = promise->get_reader(j);
+ if (act->happens_before(curr) ||
+ act->could_synchronize_with(curr)) {
+ satisfy = false;
+ break;
+ }
}
+ if (satisfy)
+ curr->get_node()->set_promise(i);
}
}
{
for (unsigned int i = 0; i < promises->size(); i++) {
Promise *promise = (*promises)[i];
- const ModelAction *act = promise->get_action();
- if ((old_cv == NULL || !old_cv->synchronized_since(act)) &&
- merge_cv->synchronized_since(act)) {
- if (promise->eliminate_thread(tid)) {
- //Promise has failed
- priv->failed_promise = true;
- return;
+ if (!promise->thread_is_available(tid))
+ continue;
+ for (unsigned int j = 0; j < promise->get_num_readers(); j++) {
+ const ModelAction *act = promise->get_reader(j);
+ if ((!old_cv || !old_cv->synchronized_since(act)) &&
+ merge_cv->synchronized_since(act)) {
+ if (promise->eliminate_thread(tid)) {
+ /* Promise has failed */
+ priv->failed_promise = true;
+ return;
+ }
}
}
}
for (unsigned int i = 0; i < promises->size(); i++) {
Promise *promise = (*promises)[i];
- const ModelAction *pread = promise->get_action();
// Is this promise on the same location?
- if (!pread->same_var(write))
+ if (promise->get_value() != write->get_value())
continue;
- if (pread->happens_before(act) && mo_graph->checkPromise(write, promise)) {
- priv->failed_promise = true;
- return;
+ for (unsigned int j = 0; j < promise->get_num_readers(); j++) {
+ const ModelAction *pread = promise->get_reader(j);
+ if (!pread->happens_before(act))
+ continue;
+ if (mo_graph->checkPromise(write, promise)) {
+ priv->failed_promise = true;
+ return;
+ }
+ break;
}
// Don't do any lookups twice for the same thread
/* Inherit existing, promised future values */
for (i = 0; i < promises->size(); i++) {
const Promise *promise = (*promises)[i];
- const ModelAction *promise_read = promise->get_action();
+ const ModelAction *promise_read = promise->get_reader(0);
if (promise_read->same_var(curr)) {
/* Only add feasible future-values */
mo_graph->startChanges();
Promise::Promise(ModelAction *read, struct future_value fv) :
num_available_threads(0),
fv(fv),
- read(read),
+ readers(1, read),
write(NULL)
{
add_thread(fv.tid);
eliminate_thread(read->get_tid());
}
+/**
+ * Add a reader that reads from this Promise. Must be added in an order
+ * consistent with execution order.
+ *
+ * @param reader The ModelAction that reads from this promise. Must be a read.
+ * @return True if this new reader has invalidated the promise; false otherwise
+ */
+bool Promise::add_reader(ModelAction *reader)
+{
+ readers.push_back(reader);
+ return eliminate_thread(reader->get_tid());
+}
+
+/**
+ * Access a reader that read from this Promise. Readers must be inserted in
+ * order by execution order, so they can be returned in this order.
+ *
+ * @param i The index of the reader to return
+ * @return The i'th reader of this Promise
+ */
+ModelAction * Promise::get_reader(unsigned int i) const
+{
+ return i < readers.size() ? readers[i] : NULL;
+}
+
/**
* Eliminate a thread which no longer can satisfy this promise. Once all
* enabled threads have been eliminated, this promise is unresolvable.
/** @brief Print debug info about the Promise */
void Promise::print() const
{
- model_print("Promised value %#" PRIx64 ", read from thread %d, available threads to resolve: ", fv.value, id_to_int(read->get_tid()));
+ model_print("Promised value %#" PRIx64 ", first read from thread %d, available threads to resolve: ", fv.value, id_to_int(get_reader(0)->get_tid()));
for (unsigned int i = 0; i < available_thread.size(); i++)
if (available_thread[i])
model_print("[%d]", i);
*/
bool Promise::is_compatible(const ModelAction *act) const
{
- return thread_is_available(act->get_tid()) && read->same_var(act);
+ return thread_is_available(act->get_tid()) && get_reader(0)->same_var(act);
}
/**