USER_O=userprog.o
USER_H=libthreads.h
-MODEL_CC=libthreads.cc schedule.cc model.cc threads.cc librace.cc action.cc nodestack.cc clockvector.cc main.cc snapshot-interface.cc cyclegraph.cc datarace.cc impatomic.cc cmodelint.cc
-MODEL_O=libthreads.o schedule.o model.o threads.o librace.o action.o nodestack.o clockvector.o main.o snapshot-interface.o cyclegraph.o datarace.o impatomic.o cmodelint.o
-MODEL_H=libthreads.h schedule.h common.h model.h threads.h librace.h action.h nodestack.h clockvector.h snapshot-interface.h cyclegraph.h hashtable.h datarace.h config.h include/impatomic.h include/cstdatomic include/stdatomic.h cmodelint.h
+MODEL_CC=libthreads.cc schedule.cc model.cc threads.cc librace.cc action.cc nodestack.cc clockvector.cc main.cc snapshot-interface.cc cyclegraph.cc datarace.cc impatomic.cc cmodelint.cc promise.cc
+MODEL_O=libthreads.o schedule.o model.o threads.o librace.o action.o nodestack.o clockvector.o main.o snapshot-interface.o cyclegraph.o datarace.o impatomic.o cmodelint.o promise.o
+MODEL_H=libthreads.h schedule.h common.h model.h threads.h librace.h action.h nodestack.h clockvector.h snapshot-interface.h cyclegraph.h hashtable.h datarace.h config.h include/impatomic.h include/cstdatomic include/stdatomic.h cmodelint.h promise.h
SHMEM_CC=snapshot.cc malloc.c mymemory.cc
SHMEM_O=snapshot.o malloc.o mymemory.o
#include "common.h"
#include "clockvector.h"
#include "cyclegraph.h"
+#include "promise.h"
#define INITIAL_THREAD_ID 0
thread_map(new HashTable<int, Thread *, int>()),
obj_map(new HashTable<const void *, action_list_t, uintptr_t, 4>()),
obj_thrd_map(new HashTable<void *, std::vector<action_list_t>, uintptr_t, 4 >()),
+ promises(new std::vector<Promise *>(1)),
thrd_last_action(new std::vector<ModelAction *>(1)),
node_stack(new NodeStack()),
next_backtrack(NULL),
#include "threads.h"
#include "action.h"
#include "clockvector.h"
+#include "hashtable.h"
/* Forward declaration */
class NodeStack;
class CycleGraph;
+class Promise;
/** @brief The central structure for model-checking */
class ModelChecker {
HashTable<const void *, action_list_t, uintptr_t, 4> *obj_map;
HashTable<void *, std::vector<action_list_t>, uintptr_t, 4 > *obj_thrd_map;
+ std::vector<Promise *> * promises;
std::vector<ModelAction *> *thrd_last_action;
NodeStack *node_stack;
ModelAction *next_backtrack;
backtrack(num_threads),
numBacktracks(0),
may_read_from(),
- read_from_index(0)
+ read_from_index(0),
+ future_values(),
+ future_index(0)
{
if (act)
act->set_node(this);
(*it)->print();
}
+/**
+ * Adds a value from a weakly ordered future write to backtrack to.
+ * @param value is the value to backtrack to.
+ */
+
+void Node::add_future_value(uint64_t value) {
+ for(int i=0;i<future_values.size();i++)
+ if (future_values[i]==value)
+ return;
+ future_values.push_back(value);
+}
+
+
/**
* Checks if the Thread associated with this thread ID has been explored from
* this Node already.
return ((read_from_index+1)>=may_read_from.size());
}
+/**
+ * Checks whether the future_values set for this node is empty.
+ * @return true if the future_values set is empty.
+ */
+
+bool Node::futurevalues_empty() {
+ return ((future_index+1)>=future_values.size());
+}
+
/**
- * Mark the appropriate backtracking infromation for exploring a thread choice.
+ * Mark the appropriate backtracking information for exploring a thread choice.
* @param act The ModelAction to explore
*/
void Node::explore_child(ModelAction *act)
may_read_from.push_back(act);
}
+/**
+ * Gets the next 'future_value' value from this Node. Only valid for a node
+ * where this->action is a 'read'.
+ * @return The first element in future_values
+ */
+
+uint64_t Node::get_future_value() {
+ ASSERT(future_index<future_values.size());
+ return future_values[future_index];
+}
+
/**
* Gets the next 'may_read_from' action from this Node. Only valid for a node
* where this->action is a 'read'.
return (read_from_index<may_read_from.size());
}
+/**
+ * Increments the index into the future_values set to explore the next item.
+ * @return Returns false if we have explored all values.
+ */
+
+bool Node::increment_future_values() {
+ future_index++;
+ return (future_index<future_values.size());
+}
+
void Node::explore(thread_id_t tid)
{
int i = id_to_int(tid);
class ModelAction;
typedef std::vector< const ModelAction *, MyAlloc< const ModelAction * > > readfrom_set_t;
+typedef std::vector< uint64_t, MyAlloc< uint64_t > > futurevalues_t;
/**
* @brief A single node in a NodeStack
/* return true = backtrack set is empty */
bool backtrack_empty();
bool readsfrom_empty();
+ bool futurevalues_empty();
void explore_child(ModelAction *act);
/* return false = thread was already in backtrack */
bool set_backtrack(thread_id_t id);
* occurred previously in the stack. */
Node * get_parent() const { return parent; }
+ void add_future_value(uint64_t value);
void add_read_from(const ModelAction *act);
const ModelAction * get_read_from();
+ uint64_t get_future_value();
bool increment_read_from();
+ bool increment_future_values();
void print();
void print_may_read_from();
* from. Only meaningful if this Node represents a 'read' action. */
readfrom_set_t may_read_from;
unsigned int read_from_index;
+
+ futurevalues_t future_values;
+ unsigned int future_index;
};
typedef std::list< Node *, MyAlloc< Node * > > node_list_t;
--- /dev/null
+#include "promise.h"
+
+Promise::Promise(ModelAction *act, uint64_t value) {
+ this->value=value;
+ this->read=act;
+ this->numthreads=1;
+}
+
--- /dev/null
+/** @file promise.h
+ *
+ * @brief Promise class --- tracks future obligations for execution
+ * related to weakly ordered writes.
+ */
+
+#ifndef __PROMISE_H__
+#define __PROMISE_H__
+#include <inttypes.h>
+
+
+class ModelAction;
+
+class Promise {
+ public:
+ Promise(ModelAction * act, uint64_t value);
+ private:
+ uint64_t value;
+ ModelAction *read;
+ unsigned int numthreads;
+};
+
+#endif