X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=execution.cc;fp=execution.cc;h=4953718d360499b85dfa8eed8bc6d8415bc1e33a;hb=3f376daab54b640efb30700f83bc3ab1cfb88848;hp=4b8461e8f678c38302e6551f1ec56ecdc69d11ac;hpb=ab6885beecafb5ae9103845c03a6e72ddacd79ec;p=c11tester.git diff --git a/execution.cc b/execution.cc index 4b8461e8..4953718d 100644 --- a/execution.cc +++ b/execution.cc @@ -2,6 +2,7 @@ #include #include #include +#include #include "model.h" #include "execution.h" @@ -247,10 +248,8 @@ void ModelExecution::restore_last_seq_num() * @param thread The thread that we might wake up * @return True, if we should wake up the sleeping thread; false otherwise */ -bool ModelExecution::should_wake_up(const Thread *thread) const +bool ModelExecution::should_wake_up(const ModelAction * asleep) const { - const ModelAction *asleep = thread->get_pending(); - /* The sleep is literally sleeping */ switch (asleep->get_type()) { case THREAD_SLEEP: @@ -275,14 +274,16 @@ void ModelExecution::wake_up_sleeping_actions() thread_id_t tid = int_to_id(i); if (scheduler->is_sleep_set(tid)) { Thread *thr = get_thread(tid); - if (should_wake_up(thr)) { + ModelAction * pending = thr->get_pending(); + if (should_wake_up(pending)) { /* Remove this thread from sleep set */ scheduler->remove_sleep(thr); - ModelAction * pending = thr->get_pending(); + if (pending->is_sleep()) { thr->set_wakeup_state(true); } else if (pending->is_wait()) { thr->set_wakeup_state(true); + /* Remove this thread from list of waiters */ simple_action_list_t *waiters = get_safe_ptr_action(&condvar_waiters_map, pending->get_location()); for (sllnode * rit = waiters->begin();rit != NULL;rit=rit->getNext()) { if (rit->getVal()->get_tid() == tid) { @@ -290,6 +291,10 @@ void ModelExecution::wake_up_sleeping_actions() break; } } + + /* Set ETIMEDOUT error */ + if (pending->is_timedwait()) + thr->set_return_value(ETIMEDOUT); } } } @@ -507,24 +512,38 @@ bool ModelExecution::process_mutex(ModelAction *curr) waiters->push_back(curr); curr_thrd->set_pending(curr); // Forbid this thread to stash a new action - if (fuzzer->waitShouldFail(curr)) - scheduler->add_sleep(curr_thrd); // Place this thread into THREAD_SLEEP_SET + if (fuzzer->waitShouldFail(curr)) // If wait should fail spuriously, + scheduler->add_sleep(curr_thrd); // place this thread into THREAD_SLEEP_SET else scheduler->sleep(curr_thrd); 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... + case ATOMIC_TIMEDWAIT: { + Thread *curr_thrd = get_thread(curr); + if (!fuzzer->randomizeWaitTime(curr)) { + curr_thrd->set_return_value(ETIMEDOUT); + return false; + } + /* wake up the other threads */ + for (unsigned int i = 0;i < get_num_threads();i++) { + Thread *t = get_thread(int_to_id(i)); + 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; + + /* disable this thread */ + simple_action_list_t * waiters = get_safe_ptr_action(&condvar_waiters_map, curr->get_location()); + waiters->push_back(curr); + curr_thrd->set_pending(curr); // Forbid this thread to stash a new action + scheduler->add_sleep(curr_thrd); + break; + } + case ATOMIC_UNLOCK: { // TODO: lock count for recursive mutexes /* wake up the other threads */ Thread *curr_thrd = get_thread(curr);