#include "mutex.h"
#include <condition_variable>
-#include <assert.h>
/* global "model" object */
#include "model.h"
#include "execution.h"
+#include <errno.h>
int pthread_create(pthread_t *t, const pthread_attr_t * attr,
pthread_start_t start_routine, void * arg) {
}
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);
return 0;
}
+/* Take care of both pthread_yield and c++ thread yield */
+int sched_yield() {
+ model->switch_to_master(new ModelAction(THREAD_YIELD, std::memory_order_seq_cst, thread_current(), VALUE_NONE));
+ 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));
- while(1) ;//make warning goaway
+ 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 *) {
- cdsc::snapmutex *m = new cdsc::snapmutex();
-
if (!model) {
snapshot_system_init(10000, 1024, 1024, 40000);
model = new ModelChecker();
model->startChecker();
}
+ cdsc::snapmutex *m = new cdsc::snapmutex();
ModelExecution *execution = model->get_execution();
execution->getMutexMap()->put(p_mutex, m);
model->startChecker();
}
-
ModelExecution *execution = model->get_execution();
/* to protect the case where PTHREAD_MUTEX_INITIALIZER is used
if (m != NULL) {
m->lock();
} else {
- printf("ah\n");
+ return 1;
}
return 0;
}
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::snapmutex *m = execution->getMutexMap()->get(p_mutex);
return m->try_lock();
m->unlock();
} else {
printf("try to unlock an untracked pthread_mutex\n");
+ return 1;
}
return 0;
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::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;
+ 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
+ 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)) {
+ pthread_mutex_init(p_mutex, NULL);
+ }
+
+ cdsc::snapmutex *m = execution->getMutexMap()->get(p_mutex);
+
+ if (m != NULL) {
+ m->lock();
+ return 0;
+ }
+
+ return 1;
}
pthread_t pthread_self() {
+ if (!model) {
+ snapshot_system_init(10000, 1024, 1024, 40000);
+ model = new ModelChecker();
+ model->startChecker();
+ }
+
Thread* th = model->get_current_thread();
return (pthread_t)th->get_id();
}
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
ModelExecution *execution = model->get_execution();
if ( !execution->getCondMap()->contains(p_cond) )
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);
-// printf("timed_wait called\n");
+ model->switch_to_master(new ModelAction(ATOMIC_TIMEDWAIT, std::memory_order_seq_cst, v, (uint64_t) m));
+ m->lock();
+
+ // model_print("Timed_wait is called\n");
return 0;
}
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;
+}
+
+/* https://github.com/lattera/glibc/blob/master/nptl/pthread_getattr_np.c */
+int pthread_getattr_np(pthread_t t, pthread_attr_t *attr)
+{
+ ModelExecution *execution = model->get_execution();
+ Thread *th = execution->get_pthread(t);
+
+ struct pthread_attr *iattr = (struct pthread_attr *) attr;
+
+ /* The sizes are subject to alignment. */
+ if (th != NULL) {
+#if _STACK_GROWS_DOWN
+ ASSERT(false);
+#else
+ iattr->stackaddr = (char *) th->get_stack_addr();
+#endif
+
+ } else {
+ ASSERT(false);
+ }
+
+ return 0;
+}
+
+int pthread_setname_np(pthread_t t, const char *name)
+{
+ ModelExecution *execution = model->get_execution();
+ Thread *th = execution->get_pthread(t);
+
+ if (th != NULL)
+ return 0;
+
+ return 1;
+}