From 95ee0b6522a582a1a4501c12244d661905ba8a00 Mon Sep 17 00:00:00 2001 From: weiyu Date: Fri, 1 Feb 2019 12:35:42 -0800 Subject: [PATCH] pthread_join is able to return values --- include/pthread.h | 107 +++++++++++++++++++++++++++++++++++++++++++++ include/wildcard.h | 2 +- pthread.cc | 21 ++++++++- threads-model.h | 7 +++ threads.cc | 4 +- 5 files changed, 137 insertions(+), 4 deletions(-) diff --git a/include/pthread.h b/include/pthread.h index 0e05788e..92b1d1b8 100644 --- a/include/pthread.h +++ b/include/pthread.h @@ -6,6 +6,28 @@ #define PTHREAD_H 1 #include +#include +#include + +enum +{ + PTHREAD_MUTEX_TIMED_NP, + PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_ADAPTIVE_NP +#if defined __USE_UNIX98 || defined __USE_XOPEN2K8 + , + PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_TIMED_NP, + PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL +#endif +#ifdef __USE_GNU + /* For compatibility. */ + , PTHREAD_MUTEX_FAST_NP = PTHREAD_MUTEX_TIMED_NP +#endif +}; + typedef void *(*pthread_start_t)(void *); @@ -26,4 +48,89 @@ int pthread_mutex_unlock(pthread_mutex_t *); int user_main(int, char**); +// --- not implemented yet --- + +int pthread_attr_destroy(pthread_attr_t *); +int pthread_attr_getdetachstate(const pthread_attr_t *, int *); +int pthread_attr_getguardsize(const pthread_attr_t *, size_t *); +int pthread_attr_getinheritsched(const pthread_attr_t *, int *); +int pthread_attr_getschedparam(const pthread_attr_t *, + struct sched_param *); +int pthread_attr_getschedpolicy(const pthread_attr_t *, int *); +int pthread_attr_getscope(const pthread_attr_t *, int *); +int pthread_attr_getstackaddr(const pthread_attr_t *, void **); +int pthread_attr_getstacksize(const pthread_attr_t *, size_t *); +int pthread_attr_init(pthread_attr_t *); +int pthread_attr_setdetachstate(pthread_attr_t *, int); +int pthread_attr_setguardsize(pthread_attr_t *, size_t); +int pthread_attr_setinheritsched(pthread_attr_t *, int); +int pthread_attr_setschedparam(pthread_attr_t *, + const struct sched_param *); +int pthread_attr_setschedpolicy(pthread_attr_t *, int); +int pthread_attr_setscope(pthread_attr_t *, int); +int pthread_attr_setstackaddr(pthread_attr_t *, void *); +int pthread_attr_setstacksize(pthread_attr_t *, size_t); +int pthread_cancel(pthread_t); +int pthread_cond_broadcast(pthread_cond_t *); +int pthread_cond_destroy(pthread_cond_t *); +int pthread_cond_init(pthread_cond_t *, const pthread_condattr_t *); +int pthread_cond_signal(pthread_cond_t *); +int pthread_cond_timedwait(pthread_cond_t *, + pthread_mutex_t *, const struct timespec *); +int pthread_cond_wait(pthread_cond_t *, pthread_mutex_t *); +int pthread_condattr_destroy(pthread_condattr_t *); +int pthread_condattr_getpshared(const pthread_condattr_t *, int *); +int pthread_condattr_init(pthread_condattr_t *); +int pthread_condattr_setpshared(pthread_condattr_t *, int); + +int pthread_detach(pthread_t); +int pthread_equal(pthread_t, pthread_t); +int pthread_getconcurrency(void); +int pthread_getschedparam(pthread_t, int *, struct sched_param *); +void *pthread_getspecific(pthread_key_t); +int pthread_key_create(pthread_key_t *, void (*)(void *)); +int pthread_key_delete(pthread_key_t); +int pthread_mutex_destroy(pthread_mutex_t *); +int pthread_mutex_getprioceiling(const pthread_mutex_t *, int *); +int pthread_mutex_setprioceiling(pthread_mutex_t *, int, int *); +int pthread_mutexattr_destroy(pthread_mutexattr_t *); +int pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *, + int *); +int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *, int *); +int pthread_mutexattr_getpshared(const pthread_mutexattr_t *, int *); +int pthread_mutexattr_gettype(const pthread_mutexattr_t *, int *); +int pthread_mutexattr_init(pthread_mutexattr_t *); +int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *, int); +int pthread_mutexattr_setprotocol(pthread_mutexattr_t *, int); +int pthread_mutexattr_setpshared(pthread_mutexattr_t *, int); +int pthread_mutexattr_settype(pthread_mutexattr_t *, int); +int pthread_once(pthread_once_t *, void (*)(void)); +int pthread_rwlock_destroy(pthread_rwlock_t *); +int pthread_rwlock_init(pthread_rwlock_t *, + const pthread_rwlockattr_t *); +int pthread_rwlock_rdlock(pthread_rwlock_t *); +int pthread_rwlock_tryrdlock(pthread_rwlock_t *); +int pthread_rwlock_trywrlock(pthread_rwlock_t *); +int pthread_rwlock_unlock(pthread_rwlock_t *); +int pthread_rwlock_wrlock(pthread_rwlock_t *); +int pthread_rwlockattr_destroy(pthread_rwlockattr_t *); +int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *, + int *); +int pthread_rwlockattr_init(pthread_rwlockattr_t *); +int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *, int); +pthread_t + pthread_self(void); +int pthread_setcancelstate(int, int *); +int pthread_setcanceltype(int, int *); +int pthread_setconcurrency(int); +int pthread_setschedparam(pthread_t, int , + const struct sched_param *); +int pthread_setspecific(pthread_key_t, const void *); +void pthread_testcancel(void); + +int pthread_mutex_timedlock (pthread_mutex_t *__restrict __mutex, + const struct timespec *__restrict + __abstime) __THROWNL __nonnull ((1, 2)); + +void check(); #endif diff --git a/include/wildcard.h b/include/wildcard.h index 2a18c4c3..c7b9f265 100644 --- a/include/wildcard.h +++ b/include/wildcard.h @@ -1,6 +1,6 @@ #ifndef _WILDCARD_H #define _WILDCARD_H -#include "memoryorder.h" +// #include "memoryorder.h" #define MAX_WILDCARD_NUM 50 diff --git a/pthread.cc b/pthread.cc index 39c7cfbd..d811ffef 100644 --- a/pthread.cc +++ b/pthread.cc @@ -3,15 +3,20 @@ #include "action.h" #include #include -#include /* global "model" object */ #include "model.h" +unsigned int counter = 0; // counter does not to be reset to zero. It is + // find as long as it is unique. + int pthread_create(pthread_t *t, const pthread_attr_t * attr, pthread_start_t start_routine, void * arg) { struct pthread_params params = { start_routine, arg }; + *t = counter; + counter++; + ModelAction *act = new ModelAction(PTHREAD_CREATE, std::memory_order_seq_cst, t, (uint64_t)¶ms); model->pthread_map[*t] = act; @@ -24,7 +29,13 @@ int pthread_create(pthread_t *t, const pthread_attr_t * attr, int pthread_join(pthread_t t, void **value_ptr) { ModelAction *act = model->pthread_map[t]; Thread *th = act->get_thread_operand(); + model->switch_to_master(new ModelAction(PTHREAD_JOIN, std::memory_order_seq_cst, th, id_to_int(th->get_id()))); + + // store return value + void *rtval = th->get_pthread_return(); + *value_ptr = rtval; + return 0; } @@ -34,7 +45,7 @@ void pthread_exit(void *value_ptr) { } int pthread_mutex_init(pthread_mutex_t *p_mutex, const pthread_mutexattr_t *) { - if (model->mutex_map.find(p_mutex) != model->mutex_map.end() /*&& table[p_mutex]->is_initialized()*/ ) { + if (model->mutex_map.find(p_mutex) != model->mutex_map.end() ) { model_print("Reinitialize a lock\n"); // return 1; // 0 means success; 1 means failure } @@ -61,3 +72,9 @@ int pthread_mutex_unlock(pthread_mutex_t *p_mutex) { m->unlock(); return 0; } + +void check() { + for (std::map::iterator it = model->pthread_map.begin(); it != model->pthread_map.end(); it++) { + model_print("id: %d\n", it->first); + } +} diff --git a/threads-model.h b/threads-model.h index f088bace..752731e2 100644 --- a/threads-model.h +++ b/threads-model.h @@ -74,6 +74,10 @@ public: */ uint64_t get_return_value() const { return last_action_val; } + /** @set and get the return value from pthread functions */ + void set_pthread_return(void *ret) { pthread_return = ret; } + void * get_pthread_return() { return pthread_return; } + /** @return True if this thread is finished executing */ bool is_complete() const { return state == THREAD_COMPLETED; } @@ -149,6 +153,9 @@ private: */ uint64_t last_action_val; + /** the value return from pthread functions */ + void * pthread_return; + /** @brief Is this Thread a special model-checker thread? */ const bool model_thread; }; diff --git a/threads.cc b/threads.cc index 77b13c69..1a83283a 100644 --- a/threads.cc +++ b/threads.cc @@ -54,7 +54,9 @@ void thread_startup() if (curr_thread->start_routine != NULL) { curr_thread->start_routine(curr_thread->arg); } else if (curr_thread->pstart_routine != NULL) { - curr_thread->pstart_routine(curr_thread->arg); + // set pthread return value + void *retval = curr_thread->pstart_routine(curr_thread->arg); + curr_thread->set_pthread_return(retval); } /* Finish thread properly */ model->switch_to_master(new ModelAction(THREAD_FINISH, std::memory_order_seq_cst, curr_thread)); -- 2.34.1