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
}
bool ModelAction::is_wait() const {
- return type == ATOMIC_WAIT;
+ return type == ATOMIC_WAIT || type == ATOMIC_TIMEDWAIT;
}
bool ModelAction::is_notify() 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";
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;
}
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...
/* 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: {
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:
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);
threadlist[*numthreads] = thread->get_id();
(*numthreads)++;
}
+
+bool NewFuzzer::shouldWait(const ModelAction * act)
+{
+ return random() & 1;
+}
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);
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);
}
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) )
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;
}