#include "common.h"
#include "threads-model.h"
#include "action.h"
-#include "pthread.h"
+#include "mypthread.h"
#include "snapshot-interface.h"
#include "datarace.h"
#include "mutex.h"
#include <condition_variable>
-#include <assert.h>
/* global "model" object */
#include "model.h"
#include "execution.h"
-
-static void param_defaults(struct model_params *params)
-{
- params->enabledcount = 1;
- params->bound = 0;
- params->verbose = !!DBG_ENABLED();
- params->uninitvalue = 0;
- params->maxexecutions = 0;
-}
-
-static void model_main()
-{
- struct model_params params;
-
- param_defaults(¶ms);
-
- //parse_options(¶ms, main_argc, main_argv);
-
- //Initialize race detector
- initRaceDetector();
-
- snapshot_stack_init();
-
- model = new ModelChecker(params); // L: Model thread is created
-// install_trace_analyses(model->get_execution()); L: disable plugin
-
- snapshot_record(0);
- model->run();
- delete model;
-
- DEBUG("Exiting\n");
+extern "C" {
+int nanosleep(const struct timespec *rqtp, struct timespec *rmtp);
+}
+
+int nanosleep(const struct timespec *rqtp, struct timespec *rmtp) {
+ if (model) {
+ uint64_t time = rqtp->tv_sec * 1000000000 + rqtp->tv_nsec;
+ struct timespec currtime;
+ clock_gettime(CLOCK_MONOTONIC, &currtime);
+ uint64_t lcurrtime = currtime.tv_sec * 1000000000 + currtime.tv_nsec;
+ model->switch_to_master(new ModelAction(THREAD_SLEEP, std::memory_order_seq_cst, time, lcurrtime));
+ if (rmtp != NULL) {
+ clock_gettime(CLOCK_MONOTONIC, &currtime);
+ uint64_t lendtime = currtime.tv_sec * 1000000000 + currtime.tv_nsec;
+ uint64_t elapsed = lendtime - lcurrtime;
+ rmtp->tv_sec = elapsed / 1000000000;
+ rmtp->tv_nsec = elapsed - rmtp->tv_sec * 1000000000;
+ }
+ }
+ return 0;
}
int pthread_create(pthread_t *t, const pthread_attr_t * attr,
- pthread_start_t start_routine, void * arg) {
+ pthread_start_t start_routine, void * arg) {
+ if (!model) {
+ snapshot_system_init(10000, 1024, 1024, 40000);
+ model = new ModelChecker();
+ model->startChecker();
+ }
+
struct pthread_params params = { start_routine, arg };
ModelAction *act = new ModelAction(PTHREAD_CREATE, std::memory_order_seq_cst, t, (uint64_t)¶ms);
}
int pthread_join(pthread_t t, void **value_ptr) {
-// Thread *th = model->get_pthread(t);
ModelExecution *execution = model->get_execution();
Thread *th = execution->get_pthread(t);
// store return value
void *rtval = th->get_pthread_return();
*value_ptr = rtval;
- }
+ }
+ return 0;
+}
+
+int pthread_detach(pthread_t t) {
+ //Doesn't do anything
+ //Return success
return 0;
}
void pthread_exit(void *value_ptr) {
Thread * th = thread_current();
- model->switch_to_master(new ModelAction(THREAD_FINISH, std::memory_order_seq_cst, th));
+ th->set_pthread_return(value_ptr);
+ model->switch_to_master(new ModelAction(THREADONLY_FINISH, std::memory_order_seq_cst, th));
+ //Need to exit so we don't return to the program
+ real_pthread_exit(NULL);
}
int pthread_mutex_init(pthread_mutex_t *p_mutex, const pthread_mutexattr_t *) {
if (!model) {
- snapshot_system_init(10000, 1024, 1024, 40000, &model_main);
+ snapshot_system_init(10000, 1024, 1024, 40000);
+ model = new ModelChecker();
+ model->startChecker();
}
-
- cdsc::mutex *m = new cdsc::mutex();
+ cdsc::snapmutex *m = new cdsc::snapmutex();
ModelExecution *execution = model->get_execution();
execution->getMutexMap()->put(p_mutex, m);
+
return 0;
}
int pthread_mutex_lock(pthread_mutex_t *p_mutex) {
+ if (!model) {
+ snapshot_system_init(10000, 1024, 1024, 40000);
+ model = new ModelChecker();
+ model->startChecker();
+ }
+
ModelExecution *execution = model->get_execution();
- /* to protect the case where PTHREAD_MUTEX_INITIALIZER is used
+ /* to protect the case where PTHREAD_MUTEX_INITIALIZER is used
instead of pthread_mutex_init, or where *p_mutex is not stored
in the execution->mutex_map for some reason. */
- if (!execution->getMutexMap()->contains(p_mutex)) {
+ if (!execution->getMutexMap()->contains(p_mutex)) {
pthread_mutex_init(p_mutex, NULL);
}
- cdsc::mutex *m = execution->getMutexMap()->get(p_mutex);
+ cdsc::snapmutex *m = execution->getMutexMap()->get(p_mutex);
if (m != NULL) {
m->lock();
}
int pthread_mutex_trylock(pthread_mutex_t *p_mutex) {
+ if (!model) {
+ snapshot_system_init(10000, 1024, 1024, 40000);
+ model = new ModelChecker();
+ model->startChecker();
+ }
+
ModelExecution *execution = model->get_execution();
- cdsc::mutex *m = execution->getMutexMap()->get(p_mutex);
+ cdsc::snapmutex *m = execution->getMutexMap()->get(p_mutex);
return m->try_lock();
}
-int pthread_mutex_unlock(pthread_mutex_t *p_mutex) {
+int pthread_mutex_unlock(pthread_mutex_t *p_mutex) {
ModelExecution *execution = model->get_execution();
- cdsc::mutex *m = execution->getMutexMap()->get(p_mutex);
+ cdsc::snapmutex *m = execution->getMutexMap()->get(p_mutex);
if (m != NULL) {
m->unlock();
}
int pthread_mutex_timedlock (pthread_mutex_t *__restrict p_mutex,
- const struct timespec *__restrict abstime) {
+ const struct timespec *__restrict abstime) {
// timedlock just gives the option of giving up the lock, so return and let the scheduler decide which thread goes next
/*
- ModelExecution *execution = model->get_execution();
- if (!execution->mutex_map.contains(p_mutex)) {
- pthread_mutex_init(p_mutex, NULL);
- }
- cdsc::mutex *m = execution->mutex_map.get(p_mutex);
-
- if (m != NULL) {
- m->lock();
- } else {
- printf("something is wrong with pthread_mutex_timedlock\n");
- }
-
- printf("pthread_mutex_timedlock is called. It is currently implemented as a normal lock operation without no timeout\n");
-*/
+ ModelExecution *execution = model->get_execution();
+ if (!execution->mutex_map.contains(p_mutex)) {
+ pthread_mutex_init(p_mutex, NULL);
+ }
+ cdsc::snapmutex *m = execution->mutex_map.get(p_mutex);
+
+ if (m != NULL) {
+ m->lock();
+ } else {
+ printf("something is wrong with pthread_mutex_timedlock\n");
+ }
+
+ printf("pthread_mutex_timedlock is called. It is currently implemented as a normal lock operation without no timeout\n");
+ */
return 0;
}
pthread_t pthread_self() {
Thread* th = model->get_current_thread();
- return th->get_id();
+ return (pthread_t)th->get_id();
}
int pthread_key_delete(pthread_key_t) {
}
int pthread_cond_init(pthread_cond_t *p_cond, const pthread_condattr_t *attr) {
- cdsc::condition_variable *v = new cdsc::condition_variable();
+ cdsc::snapcondition_variable *v = new cdsc::snapcondition_variable();
ModelExecution *execution = model->get_execution();
execution->getCondMap()->put(p_cond, v);
if ( !execution->getCondMap()->contains(p_cond) )
pthread_cond_init(p_cond, NULL);
- cdsc::condition_variable *v = execution->getCondMap()->get(p_cond);
- cdsc::mutex *m = execution->getMutexMap()->get(p_mutex);
+ cdsc::snapcondition_variable *v = execution->getCondMap()->get(p_cond);
+ cdsc::snapmutex *m = execution->getMutexMap()->get(p_mutex);
v->wait(*m);
return 0;
}
-int pthread_cond_timedwait(pthread_cond_t *p_cond,
- pthread_mutex_t *p_mutex, const struct timespec *abstime) {
+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
ModelExecution *execution = model->get_execution();
if ( !execution->getMutexMap()->contains(p_mutex) )
pthread_mutex_init(p_mutex, NULL);
- cdsc::condition_variable *v = execution->getCondMap()->get(p_cond);
- cdsc::mutex *m = execution->getMutexMap()->get(p_mutex);
+ cdsc::snapcondition_variable *v = execution->getCondMap()->get(p_cond);
+// cdsc::snapmutex *m = execution->getMutexMap()->get(p_mutex);
model->switch_to_master(new ModelAction(NOOP, std::memory_order_seq_cst, v));
// v->wait(*m);
if ( !execution->getCondMap()->contains(p_cond) )
pthread_cond_init(p_cond, NULL);
- cdsc::condition_variable *v = execution->getCondMap()->get(p_cond);
+ cdsc::snapcondition_variable *v = execution->getCondMap()->get(p_cond);
v->notify_one();
return 0;
}
+
+int pthread_cond_broadcast(pthread_cond_t *p_cond) {
+ // notify all blocked threads
+ ModelExecution *execution = model->get_execution();
+ if ( !execution->getCondMap()->contains(p_cond) )
+ pthread_cond_init(p_cond, NULL);
+
+ cdsc::snapcondition_variable *v = execution->getCondMap()->get(p_cond);
+
+ v->notify_all();
+ return 0;
+}
+
+int pthread_cond_destroy(pthread_cond_t *p_cond) {
+ ModelExecution *execution = model->get_execution();
+
+ if (execution->getCondMap()->contains(p_cond)) {
+ cdsc::snapcondition_variable *v = execution->getCondMap()->get(p_cond);
+ delete v;
+ execution->getCondMap()->remove(p_cond);
+ }
+ return 0;
+}