From cae88a8c7de282bc4c76fa5c75e5f37107bcd5d0 Mon Sep 17 00:00:00 2001 From: weiyu Date: Fri, 3 Apr 2020 15:37:22 -0700 Subject: [PATCH] Do not report deadlock on relocking a recursive mutex; lock count not implemented yet --- execution.cc | 12 +++++++++++- include/mutex.h | 7 +++++-- include/mypthread.h | 9 +++++++++ mutex.cc | 6 +++++- pthread.cc | 9 +++++++-- threads.cc | 8 ++++++++ 6 files changed, 45 insertions(+), 6 deletions(-) diff --git a/execution.cc b/execution.cc index 97e58511..d455b516 100644 --- a/execution.cc +++ b/execution.cc @@ -376,6 +376,8 @@ bool ModelExecution::process_mutex(ModelAction *curr) //TODO: FIND SOME BETTER WAY TO CHECK LOCK INITIALIZED OR NOT //if (curr->get_cv()->getClock(state->alloc_tid) <= state->alloc_clock) // assert_bug("Lock access before initialization"); + + // TODO: lock count for recursive mutexes state->locked = get_thread(curr); ModelAction *unlock = get_last_unlock(curr); //synchronize with the previous unlock statement @@ -417,6 +419,7 @@ bool ModelExecution::process_mutex(ModelAction *curr) //FAILS AND IN THE CASE IT DOESN'T... TIMED WAITS //MUST EVENMTUALLY RELEASE... + // TODO: lock count for recursive mutexes /* wake up the other threads */ for (unsigned int i = 0;i < get_num_threads();i++) { Thread *t = get_thread(int_to_id(i)); @@ -691,8 +694,15 @@ bool ModelExecution::check_action_enabled(ModelAction *curr) { if (curr->is_lock()) { cdsc::mutex *lock = curr->get_mutex(); struct cdsc::mutex_state *state = lock->get_state(); - if (state->locked) + if (state->locked) { + Thread *lock_owner = (Thread *)state->locked; + Thread *curr_thread = get_thread(curr); + if (lock_owner == curr_thread && state->type == PTHREAD_MUTEX_RECURSIVE) { + return true; + } + return false; + } } else if (curr->is_thread_join()) { Thread *blocking = curr->get_thread_operand(); if (!blocking->is_complete()) { diff --git a/include/mutex.h b/include/mutex.h index f5894952..1f573bd1 100644 --- a/include/mutex.h +++ b/include/mutex.h @@ -8,17 +8,20 @@ #include "modeltypes.h" #include "mymemory.h" +#include "mypthread.h" namespace cdsc { struct mutex_state { void *locked; /* Thread holding the lock */ thread_id_t alloc_tid; modelclock_t alloc_clock; + int type; + int lock_count; }; class mutex { public: - mutex(); + mutex(int type = PTHREAD_MUTEX_DEFAULT); ~mutex() {} void lock(); bool try_lock(); @@ -31,7 +34,7 @@ private: class snapmutex : public mutex { public: - snapmutex() : mutex() + snapmutex(int type = 0) : mutex(type) { } SNAPSHOTALLOC }; diff --git a/include/mypthread.h b/include/mypthread.h index 4b2b615f..660a8197 100644 --- a/include/mypthread.h +++ b/include/mypthread.h @@ -9,6 +9,15 @@ #include #include +/* pthread mutex types +enum +{ + PTHREAD_MUTEX_NORMAL + PTHREAD_MUTEX_RECURSIVE + PTHREAD_MUTEX_ERRORCHECK + PTHREAD_MUTEX_DEFAULT +};*/ + typedef void *(*pthread_start_t)(void *); struct pthread_params { diff --git a/mutex.cc b/mutex.cc index 0776db8e..10fb5e32 100644 --- a/mutex.cc +++ b/mutex.cc @@ -8,13 +8,17 @@ namespace cdsc { -mutex::mutex() +mutex::mutex(int type) { state.locked = NULL; thread_id_t tid = thread_current()->get_id(); state.alloc_tid = tid; ClockVector *cv = model->get_execution()->get_cv(tid); state.alloc_clock = cv == NULL ? 0 : cv->getClock(tid); + + // For recursive mutex + state.type = type; + state.lock_count = 0; } void mutex::lock() diff --git a/pthread.cc b/pthread.cc index 706f1b75..50214c34 100644 --- a/pthread.cc +++ b/pthread.cc @@ -66,13 +66,18 @@ void pthread_exit(void *value_ptr) { real_pthread_exit(NULL); } -int pthread_mutex_init(pthread_mutex_t *p_mutex, const pthread_mutexattr_t *) { +int pthread_mutex_init(pthread_mutex_t *p_mutex, const pthread_mutexattr_t * attr) { if (!model) { snapshot_system_init(10000, 1024, 1024, 40000); model = new ModelChecker(); model->startChecker(); } - cdsc::snapmutex *m = new cdsc::snapmutex(); + + int mutex_type = PTHREAD_MUTEX_DEFAULT; + if (attr != NULL) + pthread_mutexattr_gettype(attr, &mutex_type); + + cdsc::snapmutex *m = new cdsc::snapmutex(mutex_type); ModelExecution *execution = model->get_execution(); execution->getMutexMap()->put(p_mutex, m); diff --git a/threads.cc b/threads.cc index 8b55a91b..ee0df19c 100644 --- a/threads.cc +++ b/threads.cc @@ -490,6 +490,14 @@ Thread * Thread::waiting_on() const bool Thread::is_waiting_on(const Thread *t) const { Thread *wait; + + // One thread relocks a recursive mutex + if (waiting_on() == t && pending->is_lock()) { + int mutex_type = pending->get_mutex()->get_state()->type; + if (mutex_type == PTHREAD_MUTEX_RECURSIVE) + return false; + } + for (wait = waiting_on();wait != NULL;wait = wait->waiting_on()) if (wait == t) return true; -- 2.34.1