Modify the implementation of wait and timed wait operation
authorweiyu <weiyuluo1232@gmail.com>
Fri, 6 Sep 2019 18:43:03 +0000 (11:43 -0700)
committerweiyu <weiyuluo1232@gmail.com>
Fri, 6 Sep 2019 18:43:03 +0000 (11:43 -0700)
action.cc
action.h
execution.cc
fuzzer.h
newfuzzer.cc
newfuzzer.h
pthread.cc

index f6d536ee77072feaa1db4f0aa6e6a0771ea6244f..92bb30ebbd4df62f3205fb6f42211df22b40cce0 100644 (file)
--- a/action.cc
+++ b/action.cc
@@ -236,7 +236,7 @@ bool ModelAction::is_thread_join() const
 
 bool ModelAction::is_mutex_op() const
 {
-       return type == ATOMIC_LOCK || type == ATOMIC_TRYLOCK || type == ATOMIC_UNLOCK || type == ATOMIC_WAIT || type == ATOMIC_NOTIFY_ONE || type == ATOMIC_NOTIFY_ALL;
+       return type == ATOMIC_LOCK || type == ATOMIC_TRYLOCK || type == ATOMIC_UNLOCK || type == ATOMIC_WAIT || type == ATOMIC_TIMEDWAIT || type == ATOMIC_NOTIFY_ONE || type == ATOMIC_NOTIFY_ALL;
 }
 
 bool ModelAction::is_lock() const
@@ -250,7 +250,7 @@ bool ModelAction::is_sleep() const
 }
 
 bool ModelAction::is_wait() const {
-       return type == ATOMIC_WAIT;
+       return type == ATOMIC_WAIT || type == ATOMIC_TIMEDWAIT;
 }
 
 bool ModelAction::is_notify() const {
@@ -701,6 +701,7 @@ const char * ModelAction::get_type_str() const
        case ATOMIC_UNLOCK: return "unlock";
        case ATOMIC_TRYLOCK: return "trylock";
        case ATOMIC_WAIT: return "wait";
+       case ATOMIC_TIMEDWAIT: return "timed wait";
        case ATOMIC_NOTIFY_ONE: return "notify one";
        case ATOMIC_NOTIFY_ALL: return "notify all";
        case ATOMIC_ANNOTATION: return "annotation";
index 21d46e5bac789ec34f93340d6fa973f2eb49be52..a8233eb765184ceafb4837ae171c7826fe40d6b8 100644 (file)
--- a/action.h
+++ b/action.h
@@ -73,6 +73,7 @@ typedef enum action_type {
        ATOMIC_NOTIFY_ONE,      // < A notify_one action
        ATOMIC_NOTIFY_ALL,      // < A notify all action
        ATOMIC_WAIT,    // < A wait action
+       ATOMIC_TIMEDWAIT,       // < A timed wait action
        ATOMIC_ANNOTATION,      // < An annotation action to pass information to a trace analysis
        NOOP    // no operation, which returns control to scheduler
 } action_type_t;
index c193f229348dd569959a7a613732aa080ad3b434..ee9358f91590cf110b6f1cbb3e0325f601c90e40 100644 (file)
@@ -373,7 +373,27 @@ bool ModelExecution::process_mutex(ModelAction *curr)
                }
                break;
        }
-       case ATOMIC_WAIT:
+       case ATOMIC_WAIT: {
+               /* wake up the other threads */
+               for (unsigned int i = 0;i < get_num_threads();i++) {
+                       Thread *t = get_thread(int_to_id(i));
+                       Thread *curr_thrd = get_thread(curr);
+                       if (t->waiting_on() == curr_thrd && t->get_pending()->is_lock())
+                               scheduler->wake(t);
+               }
+
+               /* unlock the lock - after checking who was waiting on it */
+               state->locked = NULL;
+
+               if (fuzzer->shouldWait(curr)) {
+                       /* disable this thread */
+                       get_safe_ptr_action(&condvar_waiters_map, curr->get_location())->push_back(curr);
+                       scheduler->sleep(get_thread(curr));
+               }
+
+               break;
+       }
+       case ATOMIC_TIMEDWAIT:
        case ATOMIC_UNLOCK: {
                //TODO: FIX WAIT SITUATION...WAITS CAN SPURIOUSLY FAIL...TIMED WAITS SHOULD PROBABLY JUST BE THE SAME AS NORMAL WAITS...THINK ABOUT PROBABILITIES THOUGH....AS IN TIMED WAIT MUST FAIL TO GUARANTEE PROGRESS...NORMAL WAIT MAY FAIL...SO NEED NORMAL WAIT TO WORK CORRECTLY IN THE CASE IT SPURIOUSLY FAILS AND IN THE CASE IT DOESN'T...  TIMED WAITS MUST EVENMTUALLY RELEASE...
 
@@ -387,10 +407,6 @@ bool ModelExecution::process_mutex(ModelAction *curr)
 
                /* unlock the lock - after checking who was waiting on it */
                state->locked = NULL;
-
-               if (!curr->is_wait())
-                       break;/* The rest is only for ATOMIC_WAIT */
-
                break;
        }
        case ATOMIC_NOTIFY_ALL: {
index 29d31edaac7456412c7269c3c6a891ee895b5697..64875f2d4518935ae49dbf38d5e254e2fcdc1cf0 100644 (file)
--- a/fuzzer.h
+++ b/fuzzer.h
@@ -15,6 +15,7 @@ public:
        Thread * selectNotify(action_list_t * waiters);
        bool shouldSleep(const ModelAction *sleep);
        bool shouldWake(const ModelAction *sleep);
+       virtual bool shouldWait(const ModelAction *wait) = 0;
        virtual void register_engine(ModelHistory * history, ModelExecution * execution) = 0;
        SNAPSHOTALLOC
 private:
index 68efd37d437a47d4a6ad064f90d67d4f0f181719..98d56f2192fa7872364453fba10227cd04fb038e 100644 (file)
@@ -52,8 +52,9 @@ int NewFuzzer::selectWrite(ModelAction *read, SnapVector<ModelAction *> * rf_set
                Thread * read_thread = execution->get_thread(tid);
                model_print("the %d read action of thread %d is unsuccessful\n", read->get_seq_number(), read_thread->get_id());
 
+               // reset thread pending action and revert sequence numbers
                read_thread->set_pending(read);
-               read->reset_seq_number();       // revert some operations
+               read->reset_seq_number();
                execution->restore_last_seq_num();
                
                conditional_sleep(read_thread);
@@ -243,3 +244,8 @@ void NewFuzzer::wake_up_paused_threads(int * threadlist, int * numthreads)
        threadlist[*numthreads] = thread->get_id();
        (*numthreads)++;
 }
+
+bool NewFuzzer::shouldWait(const ModelAction * act)
+{
+       return random() & 1;
+}
index 7de4cd7696f5afdeea7404df697c140018edda9e..db25cfd8744a8801ba4015de686c7c8199025cf4 100644 (file)
@@ -19,8 +19,9 @@ public:
 
        Thread * selectThread(int * threadlist, int numthreads);
        Thread * selectNotify(action_list_t * waiters);
-       bool shouldSleep(const ModelAction *sleep);
-       bool shouldWake(const ModelAction *sleep);
+       bool shouldSleep(const ModelAction * sleep);
+       bool shouldWake(const ModelAction * sleep);
+       bool shouldWait(const ModelAction * wait);
 
        void register_engine(ModelHistory * history, ModelExecution * execution);
 
index 63060d898eb2af5c8db5c995dd24a7c5f1e63710..d48d34b0291fd3d41328fabddc973810508bf4ff 100644 (file)
@@ -189,6 +189,8 @@ int pthread_cond_wait(pthread_cond_t *p_cond, pthread_mutex_t *p_mutex) {
        ModelExecution *execution = model->get_execution();
        if ( !execution->getCondMap()->contains(p_cond) )
                pthread_cond_init(p_cond, NULL);
+       if ( !execution->getMutexMap()->contains(p_mutex) )
+               pthread_mutex_init(p_mutex, NULL);
 
        cdsc::snapcondition_variable *v = execution->getCondMap()->get(p_cond);
        cdsc::snapmutex *m = execution->getMutexMap()->get(p_mutex);
@@ -198,8 +200,7 @@ int pthread_cond_wait(pthread_cond_t *p_cond, pthread_mutex_t *p_mutex) {
 }
 
 int pthread_cond_timedwait(pthread_cond_t *p_cond,
-                                                                                                        pthread_mutex_t *p_mutex, const struct timespec *abstime) {
-// implement cond_timedwait as a noop and let the scheduler decide which thread goes next
+       pthread_mutex_t *p_mutex, const struct timespec *abstime) {
        ModelExecution *execution = model->get_execution();
 
        if ( !execution->getCondMap()->contains(p_cond) )
@@ -208,11 +209,12 @@ int pthread_cond_timedwait(pthread_cond_t *p_cond,
                pthread_mutex_init(p_mutex, NULL);
 
        cdsc::snapcondition_variable *v = execution->getCondMap()->get(p_cond);
-//     cdsc::snapmutex *m = execution->getMutexMap()->get(p_mutex);
+       cdsc::snapmutex *m = execution->getMutexMap()->get(p_mutex);
+
+       model->switch_to_master(new ModelAction(ATOMIC_TIMEDWAIT, std::memory_order_seq_cst, v, (uint64_t) m));
+       m->lock();
 
-       model->switch_to_master(new ModelAction(NOOP, std::memory_order_seq_cst, v));
-//     v->wait(*m);
-//     printf("timed_wait called\n");
+       // model_print("Timed_wait is called\n");
        return 0;
 }