model: add 'const'
[c11tester.git] / model.cc
index 3f200ed8e1afd2e7aff81d7b0a23ae6f0cbb7a19..1264f683fb9d1aac10d24149f9778a3569ec27fd 100644 (file)
--- a/model.cc
+++ b/model.cc
@@ -40,10 +40,10 @@ ModelChecker::ModelChecker(struct model_params params) :
        earliest_diverge(NULL),
        action_trace(new action_list_t()),
        thread_map(new HashTable<int, Thread *, int>()),
-       obj_map(new HashTable<const void *, action_list_t, uintptr_t, 4>()),
-       lock_waiters_map(new HashTable<const void *, action_list_t, uintptr_t, 4>()),
-       condvar_waiters_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 >()),
+       obj_map(new HashTable<const void *, action_list_t *, uintptr_t, 4>()),
+       lock_waiters_map(new HashTable<const void *, action_list_t *, uintptr_t, 4>()),
+       condvar_waiters_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 *, SnapshotAlloc<Promise *> >()),
        futurevalues(new std::vector< struct PendingFutureValue, SnapshotAlloc<struct PendingFutureValue> >()),
        pending_rel_seqs(new std::vector< struct release_seq *, SnapshotAlloc<struct release_seq *> >()),
@@ -90,6 +90,24 @@ ModelChecker::~ModelChecker()
        delete mo_graph;
 }
 
+static action_list_t * get_safe_ptr_action(HashTable<const void *, action_list_t *, uintptr_t, 4> * hash, void * ptr) {
+       action_list_t * tmp=hash->get(ptr);
+       if (tmp==NULL) {
+               tmp=new action_list_t();
+               hash->put(ptr, tmp);
+       }
+       return tmp;
+}
+
+static std::vector<action_list_t> * get_safe_ptr_vect_action(HashTable<void *, std::vector<action_list_t> *, uintptr_t, 4> * hash, void * ptr) {
+       std::vector<action_list_t> * tmp=hash->get(ptr);
+       if (tmp==NULL) {
+               tmp=new std::vector<action_list_t>();
+               hash->put(ptr, tmp);
+       }
+       return tmp;
+}
+
 /**
  * Restores user program to initial state and resets all model-checker data
  * structures.
@@ -276,6 +294,21 @@ bool ModelChecker::is_deadlocked() const
        return blocking_threads;
 }
 
+/**
+ * Check if this is a complete execution. That is, have all thread completed
+ * execution (rather than exiting because sleep sets have forced a redundant
+ * execution).
+ *
+ * @return True if the execution is complete.
+ */
+bool ModelChecker::is_complete_execution() const
+{
+       for (unsigned int i = 0; i < get_num_threads(); i++)
+               if (is_enabled(int_to_id(i)))
+                       return false;
+       return true;
+}
+
 /**
  * Queries the model-checker for more executions to explore and, if one
  * exists, resets the model-checker state to execute a new execution.
@@ -306,7 +339,7 @@ bool ModelChecker::next_execution()
                        pending_rel_seqs->size());
 
 
-       if (isfinalfeasible() || (params.bound != 0 && priv->used_sequence_numbers > params.bound ) || DBG_ENABLED() ) {
+       if (isfinalfeasible() || DBG_ENABLED()) {
                checkDataRaces();
                print_summary();
        }
@@ -330,7 +363,7 @@ ModelAction * ModelChecker::get_last_conflict(ModelAction *act)
        case ATOMIC_WRITE:
        case ATOMIC_RMW: {
                /* linear search: from most recent to oldest */
-               action_list_t *list = obj_map->get_safe_ptr(act->get_location());
+               action_list_t *list = get_safe_ptr_action(obj_map, act->get_location());
                action_list_t::reverse_iterator rit;
                for (rit = list->rbegin(); rit != list->rend(); rit++) {
                        ModelAction *prev = *rit;
@@ -342,7 +375,7 @@ ModelAction * ModelChecker::get_last_conflict(ModelAction *act)
        case ATOMIC_LOCK:
        case ATOMIC_TRYLOCK: {
                /* linear search: from most recent to oldest */
-               action_list_t *list = obj_map->get_safe_ptr(act->get_location());
+               action_list_t *list = get_safe_ptr_action(obj_map, act->get_location());
                action_list_t::reverse_iterator rit;
                for (rit = list->rbegin(); rit != list->rend(); rit++) {
                        ModelAction *prev = *rit;
@@ -353,7 +386,7 @@ ModelAction * ModelChecker::get_last_conflict(ModelAction *act)
        }
        case ATOMIC_UNLOCK: {
                /* linear search: from most recent to oldest */
-               action_list_t *list = obj_map->get_safe_ptr(act->get_location());
+               action_list_t *list = get_safe_ptr_action(obj_map, act->get_location());
                action_list_t::reverse_iterator rit;
                for (rit = list->rbegin(); rit != list->rend(); rit++) {
                        ModelAction *prev = *rit;
@@ -364,7 +397,7 @@ ModelAction * ModelChecker::get_last_conflict(ModelAction *act)
        }
        case ATOMIC_WAIT: {
                /* linear search: from most recent to oldest */
-               action_list_t *list = obj_map->get_safe_ptr(act->get_location());
+               action_list_t *list = get_safe_ptr_action(obj_map, act->get_location());
                action_list_t::reverse_iterator rit;
                for (rit = list->rbegin(); rit != list->rend(); rit++) {
                        ModelAction *prev = *rit;
@@ -379,7 +412,7 @@ ModelAction * ModelChecker::get_last_conflict(ModelAction *act)
        case ATOMIC_NOTIFY_ALL:
        case ATOMIC_NOTIFY_ONE: {
                /* linear search: from most recent to oldest */
-               action_list_t *list = obj_map->get_safe_ptr(act->get_location());
+               action_list_t *list = get_safe_ptr_action(obj_map, act->get_location());
                action_list_t::reverse_iterator rit;
                for (rit = list->rbegin(); rit != list->rend(); rit++) {
                        ModelAction *prev = *rit;
@@ -579,7 +612,7 @@ bool ModelChecker::process_mutex(ModelAction *curr) {
                //unlock the lock
                state->islocked = false;
                //wake up the other threads
-               action_list_t *waiters = lock_waiters_map->get_safe_ptr(curr->get_location());
+               action_list_t *waiters = get_safe_ptr_action(lock_waiters_map, curr->get_location());
                //activate all the waiting threads
                for (action_list_t::iterator rit = waiters->begin(); rit != waiters->end(); rit++) {
                        scheduler->wake(get_thread(*rit));
@@ -591,7 +624,7 @@ bool ModelChecker::process_mutex(ModelAction *curr) {
                //unlock the lock
                state->islocked = false;
                //wake up the other threads
-               action_list_t *waiters = lock_waiters_map->get_safe_ptr((void *) curr->get_value());
+               action_list_t *waiters = get_safe_ptr_action(lock_waiters_map, (void *) curr->get_value());
                //activate all the waiting threads
                for (action_list_t::iterator rit = waiters->begin(); rit != waiters->end(); rit++) {
                        scheduler->wake(get_thread(*rit));
@@ -599,14 +632,14 @@ bool ModelChecker::process_mutex(ModelAction *curr) {
                waiters->clear();
                //check whether we should go to sleep or not...simulate spurious failures
                if (curr->get_node()->get_misc()==0) {
-                       condvar_waiters_map->get_safe_ptr(curr->get_location())->push_back(curr);
+                       get_safe_ptr_action(condvar_waiters_map, curr->get_location())->push_back(curr);
                        //disable us
                        scheduler->sleep(get_current_thread());
                }
                break;
        }
        case ATOMIC_NOTIFY_ALL: {
-               action_list_t *waiters = condvar_waiters_map->get_safe_ptr(curr->get_location());
+               action_list_t *waiters = get_safe_ptr_action(condvar_waiters_map, curr->get_location());
                //activate all the waiting threads
                for (action_list_t::iterator rit = waiters->begin(); rit != waiters->end(); rit++) {
                        scheduler->wake(get_thread(*rit));
@@ -615,7 +648,7 @@ bool ModelChecker::process_mutex(ModelAction *curr) {
                break;
        }
        case ATOMIC_NOTIFY_ONE: {
-               action_list_t *waiters = condvar_waiters_map->get_safe_ptr(curr->get_location());
+               action_list_t *waiters = get_safe_ptr_action(condvar_waiters_map, curr->get_location());
                int wakeupthread=curr->get_node()->get_misc();
                action_list_t::iterator it = waiters->begin();
                advance(it, wakeupthread);
@@ -839,7 +872,7 @@ bool ModelChecker::initialize_curr_action(ModelAction **curr)
                else if (newcurr->is_wait())
                        newcurr->get_node()->set_misc_max(2);
                else if (newcurr->is_notify_one()) {
-                       newcurr->get_node()->set_misc_max(condvar_waiters_map->get_safe_ptr(newcurr->get_location())->size());
+                       newcurr->get_node()->set_misc_max(get_safe_ptr_action(condvar_waiters_map, newcurr->get_location())->size());
                }
                return true; /* This was a new ModelAction */
        }
@@ -861,7 +894,7 @@ bool ModelChecker::check_action_enabled(ModelAction *curr) {
                struct std::mutex_state * state = lock->get_state();
                if (state->islocked) {
                        //Stick the action in the appropriate waiting queue
-                       lock_waiters_map->get_safe_ptr(curr->get_location())->push_back(curr);
+                       get_safe_ptr_action(lock_waiters_map, curr->get_location())->push_back(curr);
                        return false;
                }
        } else if (curr->get_type() == THREAD_JOIN) {
@@ -1005,7 +1038,8 @@ void ModelChecker::check_curr_backtracking(ModelAction * curr) {
        }
 }
 
-bool ModelChecker::promises_expired() {
+bool ModelChecker::promises_expired() const
+{
        for (unsigned int promise_index = 0; promise_index < promises->size(); promise_index++) {
                Promise *promise = (*promises)[promise_index];
                if (promise->get_expiration()<priv->used_sequence_numbers) {
@@ -1017,12 +1051,14 @@ bool ModelChecker::promises_expired() {
 
 /** @return whether the current partial trace must be a prefix of a
  * feasible trace. */
-bool ModelChecker::isfeasibleprefix() {
+bool ModelChecker::isfeasibleprefix() const
+{
        return promises->size() == 0 && pending_rel_seqs->size() == 0 && isfeasible();
 }
 
 /** @return whether the current partial trace is feasible. */
-bool ModelChecker::isfeasible() {
+bool ModelChecker::isfeasible() const
+{
        if (DBG_ENABLED() && mo_graph->checkForRMWViolation())
                DEBUG("Infeasible: RMW violation\n");
 
@@ -1031,7 +1067,8 @@ bool ModelChecker::isfeasible() {
 
 /** @return whether the current partial trace is feasible other than
  * multiple RMW reading from the same store. */
-bool ModelChecker::isfeasibleotherthanRMW() {
+bool ModelChecker::isfeasibleotherthanRMW() const
+{
        if (DBG_ENABLED()) {
                if (mo_graph->checkForCycles())
                        DEBUG("Infeasible: modification order cycles\n");
@@ -1048,7 +1085,8 @@ bool ModelChecker::isfeasibleotherthanRMW() {
 }
 
 /** Returns whether the current completed trace is feasible. */
-bool ModelChecker::isfinalfeasible() {
+bool ModelChecker::isfinalfeasible() const
+{
        if (DBG_ENABLED() && promises->size() != 0)
                DEBUG("Infeasible: unrevolved promises\n");
 
@@ -1086,7 +1124,7 @@ void ModelChecker::check_recency(ModelAction *curr, const ModelAction *rf) {
                //accidentally clear by rolling back
                if (!isfeasible())
                        return;
-               std::vector<action_list_t> *thrd_lists = obj_thrd_map->get_safe_ptr(curr->get_location());
+               std::vector<action_list_t> *thrd_lists = get_safe_ptr_vect_action(obj_thrd_map, curr->get_location());
                int tid = id_to_int(curr->get_tid());
 
                /* Skip checks */
@@ -1178,7 +1216,7 @@ void ModelChecker::check_recency(ModelAction *curr, const ModelAction *rf) {
  */
 bool ModelChecker::r_modification_order(ModelAction *curr, const ModelAction *rf)
 {
-       std::vector<action_list_t> *thrd_lists = obj_thrd_map->get_safe_ptr(curr->get_location());
+       std::vector<action_list_t> *thrd_lists = get_safe_ptr_vect_action(obj_thrd_map, curr->get_location());
        unsigned int i;
        bool added = false;
        ASSERT(curr->is_read());
@@ -1237,7 +1275,7 @@ bool ModelChecker::r_modification_order(ModelAction *curr, const ModelAction *rf
  */
 void ModelChecker::post_r_modification_order(ModelAction *curr, const ModelAction *rf)
 {
-       std::vector<action_list_t> *thrd_lists = obj_thrd_map->get_safe_ptr(curr->get_location());
+       std::vector<action_list_t> *thrd_lists = get_safe_ptr_vect_action(obj_thrd_map, curr->get_location());
        unsigned int i;
        ASSERT(curr->is_read());
 
@@ -1308,7 +1346,7 @@ void ModelChecker::post_r_modification_order(ModelAction *curr, const ModelActio
  */
 bool ModelChecker::w_modification_order(ModelAction *curr)
 {
-       std::vector<action_list_t> *thrd_lists = obj_thrd_map->get_safe_ptr(curr->get_location());
+       std::vector<action_list_t> *thrd_lists = get_safe_ptr_vect_action(obj_thrd_map, curr->get_location());
        unsigned int i;
        bool added = false;
        ASSERT(curr->is_write());
@@ -1430,7 +1468,7 @@ bool ModelChecker::thin_air_constraint_may_allow(const ModelAction * writer, con
  */
 bool ModelChecker::mo_may_allow(const ModelAction *writer, const ModelAction *reader)
 {
-       std::vector<action_list_t> *thrd_lists = obj_thrd_map->get_safe_ptr(reader->get_location());
+       std::vector<action_list_t> *thrd_lists = get_safe_ptr_vect_action(obj_thrd_map, reader->get_location());
        unsigned int i;
        /* Iterate over all threads */
        for (i = 0; i < thrd_lists->size(); i++) {
@@ -1522,7 +1560,7 @@ bool ModelChecker::release_seq_heads(const ModelAction *rf,
        /* else relaxed write; check modification order for contiguous subsequence
         * -> rf must be same thread as release */
        int tid = id_to_int(rf->get_tid());
-       std::vector<action_list_t> *thrd_lists = obj_thrd_map->get_safe_ptr(rf->get_location());
+       std::vector<action_list_t> *thrd_lists = get_safe_ptr_vect_action(obj_thrd_map, rf->get_location());
        action_list_t *list = &(*thrd_lists)[tid];
        action_list_t::const_reverse_iterator rit;
 
@@ -1720,9 +1758,9 @@ void ModelChecker::add_action_to_lists(ModelAction *act)
        int tid = id_to_int(act->get_tid());
        action_trace->push_back(act);
 
-       obj_map->get_safe_ptr(act->get_location())->push_back(act);
+       get_safe_ptr_action(obj_map, act->get_location())->push_back(act);
 
-       std::vector<action_list_t> *vec = obj_thrd_map->get_safe_ptr(act->get_location());
+       std::vector<action_list_t> *vec = get_safe_ptr_vect_action(obj_thrd_map, act->get_location());
        if (tid >= (int)vec->size())
                vec->resize(priv->next_thread_id);
        (*vec)[tid].push_back(act);
@@ -1733,9 +1771,9 @@ void ModelChecker::add_action_to_lists(ModelAction *act)
 
        if (act->is_wait()) {
                void *mutex_loc=(void *) act->get_value();
-               obj_map->get_safe_ptr(mutex_loc)->push_back(act);
+               get_safe_ptr_action(obj_map, mutex_loc)->push_back(act);
 
-               std::vector<action_list_t> *vec = obj_thrd_map->get_safe_ptr(mutex_loc);
+               std::vector<action_list_t> *vec = get_safe_ptr_vect_action(obj_thrd_map, mutex_loc);
                if (tid >= (int)vec->size())
                        vec->resize(priv->next_thread_id);
                (*vec)[tid].push_back(act);
@@ -1771,7 +1809,7 @@ ModelAction * ModelChecker::get_last_action(thread_id_t tid) const
 ModelAction * ModelChecker::get_last_seq_cst(ModelAction *curr) const
 {
        void *location = curr->get_location();
-       action_list_t *list = obj_map->get_safe_ptr(location);
+       action_list_t *list = get_safe_ptr_action(obj_map, location);
        /* Find: max({i in dom(S) | seq_cst(t_i) && isWrite(t_i) && samevar(t_i, t)}) */
        action_list_t::reverse_iterator rit;
        for (rit = list->rbegin(); rit != list->rend(); rit++)
@@ -1791,7 +1829,7 @@ ModelAction * ModelChecker::get_last_seq_cst(ModelAction *curr) const
 ModelAction * ModelChecker::get_last_unlock(ModelAction *curr) const
 {
        void *location = curr->get_location();
-       action_list_t *list = obj_map->get_safe_ptr(location);
+       action_list_t *list = get_safe_ptr_action(obj_map, location);
        /* Find: max({i in dom(S) | isUnlock(t_i) && samevar(t_i, t)}) */
        action_list_t::reverse_iterator rit;
        for (rit = list->rbegin(); rit != list->rend(); rit++)
@@ -2013,7 +2051,7 @@ void ModelChecker::compute_relseq_breakwrites(ModelAction *curr)
  */
 void ModelChecker::build_reads_from_past(ModelAction *curr)
 {
-       std::vector<action_list_t> *thrd_lists = obj_thrd_map->get_safe_ptr(curr->get_location());
+       std::vector<action_list_t> *thrd_lists = get_safe_ptr_vect_action(obj_thrd_map, curr->get_location());
        unsigned int i;
        ASSERT(curr->is_read());