fix the case where no waiter is waiting
[c11tester.git] / execution.cc
index 2a7e0dadd1e0918ac21b5f43dd4e3608935b8f18..8fdc9fbe59be737ed849582ac77b35c124d41665 100644 (file)
@@ -1,6 +1,5 @@
 #include <stdio.h>
 #include <algorithm>
-#include <mutex>
 #include <new>
 #include <stdarg.h>
 
@@ -70,9 +69,12 @@ ModelExecution::ModelExecution(ModelChecker *m,
        scheduler(scheduler),
        action_trace(),
        thread_map(2), /* We'll always need at least 2 threads */
+       pthread_map(0),
+       pthread_counter(0),
        obj_map(),
        condvar_waiters_map(),
        obj_thrd_map(),
+       mutex_map(),
        promises(),
        futurevalues(),
        pending_rel_seqs(),
@@ -83,8 +85,8 @@ ModelExecution::ModelExecution(ModelChecker *m,
        mo_graph(new CycleGraph())
 {
        /* Initialize a model-checker thread, for special ModelActions */
-       model_thread = new Thread(get_next_id());
-       add_thread(model_thread);
+       model_thread = new Thread(get_next_id());       // L: Create model thread
+       add_thread(model_thread);                       // L: Add model thread to scheduler
        scheduler->register_engine(this);
        node_stack->register_engine(this);
 }
@@ -685,8 +687,8 @@ bool ModelExecution::process_read(ModelAction *curr)
  */
 bool ModelExecution::process_mutex(ModelAction *curr)
 {
-       std::mutex *mutex = curr->get_mutex();
-       struct std::mutex_state *state = NULL;
+       cdsc::mutex *mutex = curr->get_mutex();
+       struct cdsc::mutex_state *state = NULL;
 
        if (mutex)
                state = mutex->get_state();
@@ -751,6 +753,11 @@ bool ModelExecution::process_mutex(ModelAction *curr)
                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();
+
+               // WL
+               if (it == waiters->end())
+                       break;
+
                advance(it, wakeupthread);
                scheduler->wake(get_thread(*it));
                waiters->erase(it);
@@ -947,6 +954,7 @@ bool ModelExecution::process_thread_action(ModelAction *curr)
                thrd_t *thrd = (thrd_t *)curr->get_location();
                struct thread_params *params = (struct thread_params *)curr->get_value();
                Thread *th = new Thread(get_next_id(), thrd, params->func, params->arg, get_thread(curr));
+               curr->set_thread_operand(th);
                add_thread(th);
                th->set_creation(curr);
                /* Promises can be satisfied by children */
@@ -957,6 +965,28 @@ bool ModelExecution::process_thread_action(ModelAction *curr)
                }
                break;
        }
+       case PTHREAD_CREATE: {
+               (*(pthread_t *)curr->get_location()) = pthread_counter++;       
+
+               struct pthread_params *params = (struct pthread_params *)curr->get_value();
+               Thread *th = new Thread(get_next_id(), NULL, params->func, params->arg, get_thread(curr));
+               curr->set_thread_operand(th);
+               add_thread(th);
+               th->set_creation(curr);
+
+               if ( pthread_map.size() < pthread_counter )
+                       pthread_map.resize( pthread_counter );
+               pthread_map[ pthread_counter-1 ] = th;
+
+               /* Promises can be satisfied by children */
+               for (unsigned int i = 0; i < promises.size(); i++) {
+                       Promise *promise = promises[i];
+                       if (promise->thread_is_available(curr->get_tid()))
+                               promise->add_thread(th->get_id());
+               }
+               
+               break;
+       }
        case THREAD_JOIN: {
                Thread *blocking = curr->get_thread_operand();
                ModelAction *act = get_last_action(blocking->get_id());
@@ -964,6 +994,14 @@ bool ModelExecution::process_thread_action(ModelAction *curr)
                updated = true; /* trigger rel-seq checks */
                break;
        }
+       case PTHREAD_JOIN: {
+               Thread *blocking = curr->get_thread_operand();
+               ModelAction *act = get_last_action(blocking->get_id());
+               synchronize(act, curr);
+               updated = true; /* trigger rel-seq checks */
+               break; // WL: to be add (modified)
+       }
+
        case THREAD_FINISH: {
                Thread *th = get_thread(curr);
                /* Wake up any joining threads */
@@ -1132,6 +1170,7 @@ bool ModelExecution::initialize_curr_action(ModelAction **curr)
  *
  * @return True if this read established synchronization
  */
+
 bool ModelExecution::read_from(ModelAction *act, const ModelAction *rf)
 {
        ASSERT(rf);
@@ -1214,8 +1253,8 @@ void ModelExecution::thread_blocking_check_promises(Thread *blocker, Thread *wai
  */
 bool ModelExecution::check_action_enabled(ModelAction *curr) {
        if (curr->is_lock()) {
-               std::mutex *lock = curr->get_mutex();
-               struct std::mutex_state *state = lock->get_state();
+               cdsc::mutex *lock = curr->get_mutex();
+               struct cdsc::mutex_state *state = lock->get_state();
                if (state->locked)
                        return false;
        } else if (curr->is_thread_join()) {
@@ -2347,6 +2386,7 @@ ModelAction * ModelExecution::get_last_seq_cst_fence(thread_id_t tid, const Mode
 ModelAction * ModelExecution::get_last_unlock(ModelAction *curr) const
 {
        void *location = curr->get_location();
+
        action_list_t *list = obj_map.get(location);
        /* Find: max({i in dom(S) | isUnlock(t_i) && samevar(t_i, t)}) */
        action_list_t::reverse_iterator rit;
@@ -2821,6 +2861,16 @@ Thread * ModelExecution::get_thread(const ModelAction *act) const
        return get_thread(act->get_tid());
 }
 
+/**
+ * @brief Get a Thread reference by its pthread ID
+ * @param index The pthread's ID
+ * @return A Thread reference
+ */
+Thread * ModelExecution::get_pthread(pthread_t pid) {
+        if (pid < pthread_counter + 1) return pthread_map[pid];
+        else return NULL;
+}
+
 /**
  * @brief Get a Promise's "promise number"
  *
@@ -2877,9 +2927,26 @@ Thread * ModelExecution::action_select_next_thread(const ModelAction *curr) cons
        /* Do not split atomic RMW */
        if (curr->is_rmwr())
                return get_thread(curr);
+       if (curr->is_write()) {
+//             std::memory_order order = curr->get_mo(); 
+//             switch(order) {
+//                     case std::memory_order_relaxed: 
+//                             return get_thread(curr);
+//                     case std::memory_order_release:
+//                             return get_thread(curr);
+//                     defalut:
+//                             return NULL;
+//             }       
+               return NULL;
+       }
+
        /* Follow CREATE with the created thread */
+       /* which is not needed, because model.cc takes care of this */
        if (curr->get_type() == THREAD_CREATE)
+               return curr->get_thread_operand(); 
+       if (curr->get_type() == PTHREAD_CREATE) {
                return curr->get_thread_operand();
+       }
        return NULL;
 }